Merge pull request 'issue-22-remove-legacy-components' (#28) from issue-22-remove-legacy-components into master
Reviewed-on: #28deploy_packages_to_gitea
commit
8ba0bddf04
|
|
@ -80,10 +80,7 @@
|
||||||
<Logger name="org.libreccm.security.Shiro"
|
<Logger name="org.libreccm.security.Shiro"
|
||||||
level="debug">
|
level="debug">
|
||||||
</Logger>
|
</Logger>
|
||||||
<Logger name="org.libreccm.theming.xslt.CcmUriResolver"
|
<Logger name="org.libreccm.ui.admin.usersgroupsroles.RolesController"
|
||||||
level="debug">
|
|
||||||
</Logger>
|
|
||||||
<Logger name="org.libreccm.ui.admin.usersgroupsroles.RolesController"
|
|
||||||
level="debug">
|
level="debug">
|
||||||
</Logger>
|
</Logger>
|
||||||
<Logger name="org.librecms.contentsection.AssetRepository"
|
<Logger name="org.librecms.contentsection.AssetRepository"
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,6 @@
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.sf.saxon</groupId>
|
|
||||||
<artifactId>Saxon-HE</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- CCM modules -->
|
<!-- CCM modules -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.libreccm</groupId>
|
<groupId>org.libreccm</groupId>
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import org.librecms.assets.Person;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
import org.librecms.contentsection.ContentItemRepository;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
class ProfileSiteItemController {
|
|
||||||
|
|
||||||
public static final String OWNER = "owner";
|
|
||||||
|
|
||||||
public static final String POSITION = "position";
|
|
||||||
|
|
||||||
public static final String INTERSETS = "interests";
|
|
||||||
|
|
||||||
public static final String MISC = "misc";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContentItemRepository itemRepository;
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public void setOwner(final long profileSiteItemId, final long ownerId) {
|
|
||||||
final ProfileSiteItem profileSiteItem = itemRepository
|
|
||||||
.findById(profileSiteItemId, ProfileSiteItem.class)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(
|
|
||||||
String.format(
|
|
||||||
"No ProfileSiteItem with ID %d found.",
|
|
||||||
profileSiteItemId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
final Person owner = assetRepository
|
|
||||||
.findById(ownerId, Person.class)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(
|
|
||||||
String.format(
|
|
||||||
"No Person with ID %d found.", ownerId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
profileSiteItem.setOwner(owner);
|
|
||||||
itemRepository.save(profileSiteItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosition(
|
|
||||||
final long profileSiteItemId, final String position, final Locale locale
|
|
||||||
) {
|
|
||||||
final ProfileSiteItem profileSiteItem = itemRepository
|
|
||||||
.findById(profileSiteItemId, ProfileSiteItem.class)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(
|
|
||||||
String.format(
|
|
||||||
"No ProfileSiteItem with ID %d found.",
|
|
||||||
profileSiteItemId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
profileSiteItem.getPosition().putValue(locale, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterests(
|
|
||||||
final long profileSiteItemId,
|
|
||||||
final String interests,
|
|
||||||
final Locale locale
|
|
||||||
) {
|
|
||||||
final ProfileSiteItem profileSiteItem = itemRepository
|
|
||||||
.findById(profileSiteItemId, ProfileSiteItem.class)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(
|
|
||||||
String.format(
|
|
||||||
"No ProfileSiteItem with ID %d found.",
|
|
||||||
profileSiteItemId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
profileSiteItem.getInterests().putValue(locale, interests);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMisc(
|
|
||||||
final long profileSiteItemId, final String misc, final Locale locale
|
|
||||||
) {
|
|
||||||
final ProfileSiteItem profileSiteItem = itemRepository
|
|
||||||
.findById(profileSiteItemId, ProfileSiteItem.class)
|
|
||||||
.orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(
|
|
||||||
String.format(
|
|
||||||
"No ProfileSiteItem with ID %d found.",
|
|
||||||
profileSiteItemId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
profileSiteItem.getMisc().putValue(locale, misc);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetSearchWidget;
|
|
||||||
import com.arsdigita.cms.ui.authoring.CreationSelector;
|
|
||||||
import com.arsdigita.cms.ui.authoring.PageCreateForm;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.assets.Person;
|
|
||||||
import org.librecms.contentsection.ContentItemInitializer;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemCreate extends PageCreateForm {
|
|
||||||
|
|
||||||
private final static String OWNER_SEARCH = "owner";
|
|
||||||
|
|
||||||
private AssetSearchWidget ownerSearch;
|
|
||||||
|
|
||||||
public ProfileSiteItemCreate(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final CreationSelector creationSelector,
|
|
||||||
final StringParameter selectedLanguageParam
|
|
||||||
) {
|
|
||||||
super(itemModel, creationSelector, selectedLanguageParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
ownerSearch = new AssetSearchWidget(OWNER_SEARCH, Person.class);
|
|
||||||
ownerSearch.setLabel(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site.owner.label", ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
add(ownerSearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
super.validate(event);
|
|
||||||
final FormData formData = event.getFormData();
|
|
||||||
|
|
||||||
if (!formData.containsKey(OWNER_SEARCH)
|
|
||||||
|| formData.get(OWNER_SEARCH) == null) {
|
|
||||||
formData.addError(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site.owner.not_selected",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ContentItemInitializer<ProfileSiteItem> getItemInitializer(
|
|
||||||
final FormData formData, final PageState state
|
|
||||||
) {
|
|
||||||
return (item) -> item.setOwner((Person) formData.get(OWNER_SEARCH));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemInterestsForm
|
|
||||||
extends BasicItemForm
|
|
||||||
implements FormProcessListener, FormInitListener {
|
|
||||||
|
|
||||||
private final StringParameter selectedLangParam;
|
|
||||||
|
|
||||||
public ProfileSiteItemInterestsForm(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
super("ProfileSiteItemEditInterests", itemModel, selectedLangParam);
|
|
||||||
this.selectedLangParam = selectedLangParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
add(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.interests",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
final ParameterModel interestsParam = new StringParameter(
|
|
||||||
ProfileSiteItemController.POSITION);
|
|
||||||
final TextArea interests = new TextArea(interestsParam);
|
|
||||||
interests.setCols(80);
|
|
||||||
interests.setRows(8);
|
|
||||||
add(interests);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
data.put(ProfileSiteItemController.POSITION, profile.getInterests());
|
|
||||||
|
|
||||||
setVisible(state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
if ((profile != null)
|
|
||||||
&& getSaveCancelSection().getSaveButton().isSelected(state)) {
|
|
||||||
|
|
||||||
final ProfileSiteItemController controller = CdiUtil
|
|
||||||
.createCdiUtil()
|
|
||||||
.findBean(ProfileSiteItemController.class);
|
|
||||||
|
|
||||||
final Locale selectedLocale = SelectedLanguageUtil.selectedLocale(
|
|
||||||
state, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
controller.setInterests(
|
|
||||||
profile.getObjectId(),
|
|
||||||
(String) data.get(ProfileSiteItemController.POSITION),
|
|
||||||
selectedLocale
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
init(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SimpleEditStep;
|
|
||||||
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
|
|
||||||
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemInterestsStep extends SimpleEditStep {
|
|
||||||
|
|
||||||
private String EDIT_POSITION_SHEET_NAME = "editInterests";
|
|
||||||
|
|
||||||
public ProfileSiteItemInterestsStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
this(itemModel, parent, selectedLangParam, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfileSiteItemInterestsStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam,
|
|
||||||
final String prefix
|
|
||||||
) {
|
|
||||||
super(itemModel, parent, selectedLangParam, prefix);
|
|
||||||
|
|
||||||
final BasicItemForm editInterestsForm = new ProfileSiteItemInterestsForm(
|
|
||||||
itemModel, selectedLangParam
|
|
||||||
);
|
|
||||||
add(
|
|
||||||
EDIT_POSITION_SHEET_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_site.ui.interests.edit",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
new WorkflowLockedComponentAccess(parent, itemModel),
|
|
||||||
editInterestsForm.getSaveCancelSection().getCancelButton()
|
|
||||||
);
|
|
||||||
|
|
||||||
setDisplayComponent(getProfileSiteItemInterestsSheet(
|
|
||||||
itemModel, selectedLangParam)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Component getProfileSiteItemInterestsSheet(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(
|
|
||||||
itemModel, false, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
sheet.add(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.interests",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
ProfileSiteItemController.POSITION
|
|
||||||
);
|
|
||||||
|
|
||||||
return sheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemMiscForm
|
|
||||||
extends BasicItemForm
|
|
||||||
implements FormProcessListener, FormInitListener {
|
|
||||||
|
|
||||||
private final StringParameter selectedLangParam;
|
|
||||||
|
|
||||||
public ProfileSiteItemMiscForm(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
super("ProfileSiteItemEditMisc", itemModel, selectedLangParam);
|
|
||||||
this.selectedLangParam = selectedLangParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
add(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.misc",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
final ParameterModel miscParam = new StringParameter(
|
|
||||||
ProfileSiteItemController.POSITION);
|
|
||||||
final TextArea misc = new TextArea(miscParam);
|
|
||||||
misc.setCols(80);
|
|
||||||
misc.setRows(8);
|
|
||||||
add(misc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
data.put(ProfileSiteItemController.POSITION, profile.getMisc());
|
|
||||||
|
|
||||||
setVisible(state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
if ((profile != null)
|
|
||||||
&& getSaveCancelSection().getSaveButton().isSelected(state)) {
|
|
||||||
|
|
||||||
final ProfileSiteItemController controller = CdiUtil
|
|
||||||
.createCdiUtil()
|
|
||||||
.findBean(ProfileSiteItemController.class);
|
|
||||||
|
|
||||||
final Locale selectedLocale = SelectedLanguageUtil.selectedLocale(
|
|
||||||
state, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
controller.setMisc(
|
|
||||||
profile.getObjectId(),
|
|
||||||
(String) data.get(ProfileSiteItemController.POSITION),
|
|
||||||
selectedLocale
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
init(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SimpleEditStep;
|
|
||||||
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
|
|
||||||
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemMiscStep extends SimpleEditStep {
|
|
||||||
|
|
||||||
private String EDIT_POSITION_SHEET_NAME = "editMisc";
|
|
||||||
|
|
||||||
public ProfileSiteItemMiscStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
this(itemModel, parent, selectedLangParam, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfileSiteItemMiscStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam,
|
|
||||||
final String prefix
|
|
||||||
) {
|
|
||||||
super(itemModel, parent, selectedLangParam, prefix);
|
|
||||||
|
|
||||||
final BasicItemForm editMiscForm = new ProfileSiteItemMiscForm(
|
|
||||||
itemModel, selectedLangParam
|
|
||||||
);
|
|
||||||
add(
|
|
||||||
EDIT_POSITION_SHEET_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_site.ui.misc.edit",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
new WorkflowLockedComponentAccess(parent, itemModel),
|
|
||||||
editMiscForm.getSaveCancelSection().getCancelButton()
|
|
||||||
);
|
|
||||||
|
|
||||||
setDisplayComponent(getProfileSiteItemMiscSheet(
|
|
||||||
itemModel, selectedLangParam)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Component getProfileSiteItemMiscSheet(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(
|
|
||||||
itemModel, false, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
sheet.add(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.misc",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
ProfileSiteItemController.POSITION
|
|
||||||
);
|
|
||||||
|
|
||||||
return sheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemPositionForm
|
|
||||||
extends BasicItemForm
|
|
||||||
implements FormProcessListener, FormInitListener {
|
|
||||||
|
|
||||||
private final StringParameter selectedLangParam;
|
|
||||||
|
|
||||||
public ProfileSiteItemPositionForm(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
super("ProfileSiteItemEditPosition", itemModel, selectedLangParam);
|
|
||||||
this.selectedLangParam = selectedLangParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
add(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.position",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
final ParameterModel positionParam = new StringParameter(
|
|
||||||
ProfileSiteItemController.POSITION);
|
|
||||||
final TextArea position = new TextArea(positionParam);
|
|
||||||
position.setCols(80);
|
|
||||||
position.setRows(8);
|
|
||||||
add(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
data.put(ProfileSiteItemController.POSITION, profile.getPosition());
|
|
||||||
|
|
||||||
setVisible(state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
final ProfileSiteItem profile
|
|
||||||
= (ProfileSiteItem) getItemSelectionModel()
|
|
||||||
.getSelectedItem(state);
|
|
||||||
|
|
||||||
if ((profile != null)
|
|
||||||
&& getSaveCancelSection().getSaveButton().isSelected(state)) {
|
|
||||||
|
|
||||||
final ProfileSiteItemController controller = CdiUtil
|
|
||||||
.createCdiUtil()
|
|
||||||
.findBean(ProfileSiteItemController.class);
|
|
||||||
|
|
||||||
final Locale selectedLocale = SelectedLanguageUtil.selectedLocale(
|
|
||||||
state, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
controller.setPosition(
|
|
||||||
profile.getObjectId(),
|
|
||||||
(String) data.get(ProfileSiteItemController.POSITION),
|
|
||||||
selectedLocale
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
init(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SimpleEditStep;
|
|
||||||
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
|
|
||||||
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemPositionStep extends SimpleEditStep {
|
|
||||||
|
|
||||||
private String EDIT_POSITION_SHEET_NAME = "editPosition";
|
|
||||||
|
|
||||||
public ProfileSiteItemPositionStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
this(itemModel, parent, selectedLangParam, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProfileSiteItemPositionStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam,
|
|
||||||
final String prefix
|
|
||||||
) {
|
|
||||||
super(itemModel, parent, selectedLangParam, prefix);
|
|
||||||
|
|
||||||
final BasicItemForm editPositionForm = new ProfileSiteItemPositionForm(
|
|
||||||
itemModel, selectedLangParam
|
|
||||||
);
|
|
||||||
add(
|
|
||||||
EDIT_POSITION_SHEET_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_site.ui.position.edit",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
new WorkflowLockedComponentAccess(parent, itemModel),
|
|
||||||
editPositionForm.getSaveCancelSection().getCancelButton()
|
|
||||||
);
|
|
||||||
|
|
||||||
setDisplayComponent(getProfileSiteItemPositionSheet(
|
|
||||||
itemModel, selectedLangParam)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Component getProfileSiteItemPositionSheet(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(
|
|
||||||
itemModel, false, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
sheet.add(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site_item.ui.position",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
),
|
|
||||||
ProfileSiteItemController.POSITION
|
|
||||||
);
|
|
||||||
|
|
||||||
return sheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SegmentedPanel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicPageForm;
|
|
||||||
import com.arsdigita.cms.ui.authoring.SimpleEditStep;
|
|
||||||
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
|
|
||||||
|
|
||||||
import org.librecms.assets.Person;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemPropertiesStep extends SimpleEditStep {
|
|
||||||
|
|
||||||
public static final String EDIT_SHEET_NAME = "editProfileSiteItem";
|
|
||||||
|
|
||||||
public ProfileSiteItemPropertiesStep(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final AuthoringKitWizard parent,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
super(itemModel, parent, selectedLangParam);
|
|
||||||
|
|
||||||
setDefaultEditKey(EDIT_SHEET_NAME);
|
|
||||||
|
|
||||||
final SimpleEditStep basicProperties = new SimpleEditStep(
|
|
||||||
itemModel, parent, selectedLangParam, EDIT_SHEET_NAME
|
|
||||||
);
|
|
||||||
final BasicPageForm editBasicSheet = new ProfileSiteItemPropertyForm(
|
|
||||||
itemModel, this, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
basicProperties.add(
|
|
||||||
EDIT_SHEET_NAME,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
ProfileSiteConstants.BUNDLE,
|
|
||||||
"profile_site.ui.edit_basic_properties"
|
|
||||||
),
|
|
||||||
new WorkflowLockedComponentAccess(editBasicSheet, itemModel),
|
|
||||||
editBasicSheet.getSaveCancelSection().getCancelButton()
|
|
||||||
);
|
|
||||||
|
|
||||||
basicProperties.setDisplayComponent(
|
|
||||||
getProfileSiteItemPropertiesSheet(itemModel, selectedLangParam)
|
|
||||||
);
|
|
||||||
|
|
||||||
final SegmentedPanel segmentedPanel = new SegmentedPanel();
|
|
||||||
segmentedPanel.addSegment(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
ProfileSiteConstants.BUNDLE,
|
|
||||||
"profile_site.ui.basic_properties"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
basicProperties
|
|
||||||
);
|
|
||||||
|
|
||||||
setDisplayComponent(segmentedPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Component getProfileSiteItemPropertiesSheet(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(
|
|
||||||
itemModel, false, selectedLangParam
|
|
||||||
);
|
|
||||||
|
|
||||||
sheet.add(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
ProfileSiteConstants.BUNDLE, "profile_site.ui.OWNER"
|
|
||||||
),
|
|
||||||
ProfileSiteItemController.OWNER,
|
|
||||||
new OwnerFormatter()
|
|
||||||
);
|
|
||||||
|
|
||||||
return sheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class OwnerFormatter
|
|
||||||
implements DomainObjectPropertySheet.AttributeFormatter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String format(
|
|
||||||
final Object obj, final String attribute, final PageState state
|
|
||||||
) {
|
|
||||||
final ProfileSiteItem profileSiteItem = (ProfileSiteItem) obj;
|
|
||||||
|
|
||||||
final Person owner = profileSiteItem.getOwner();
|
|
||||||
|
|
||||||
if (owner == null) {
|
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
return owner.getDisplayName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.contenttypes.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetSearchWidget;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicPageForm;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.assets.Person;
|
|
||||||
import org.librecms.profilesite.ProfileSiteConstants;
|
|
||||||
import org.librecms.profilesite.ProfileSiteItem;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ProfileSiteItemPropertyForm
|
|
||||||
extends BasicPageForm
|
|
||||||
implements FormInitListener, FormProcessListener, FormValidationListener {
|
|
||||||
|
|
||||||
public static final String ID = "PublicPersonalProfile_edit";
|
|
||||||
|
|
||||||
private static final String OWNER_SEARCH = "ownerSearch";
|
|
||||||
|
|
||||||
private final ItemSelectionModel itemModel;
|
|
||||||
|
|
||||||
public ProfileSiteItemPropertyForm(
|
|
||||||
final ItemSelectionModel itemModel,
|
|
||||||
final ProfileSiteItemPropertiesStep step,
|
|
||||||
final StringParameter selectedLangParam
|
|
||||||
) {
|
|
||||||
super(ID, itemModel, selectedLangParam);
|
|
||||||
this.itemModel = itemModel;
|
|
||||||
addValidationListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
super.addWidgets();
|
|
||||||
|
|
||||||
final AssetSearchWidget ownerSearch = new AssetSearchWidget(
|
|
||||||
OWNER_SEARCH, Person.class
|
|
||||||
);
|
|
||||||
add(ownerSearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
final FormData formData = event.getFormData();
|
|
||||||
final ProfileSiteItem profileSiteItem = (ProfileSiteItem) super
|
|
||||||
.initBasicWidgets(event);
|
|
||||||
formData.put(OWNER_SEARCH, profileSiteItem.getOwner());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
super.validate(event);
|
|
||||||
|
|
||||||
final FormData formData = event.getFormData();
|
|
||||||
if (!formData.containsKey(OWNER_SEARCH)
|
|
||||||
|| formData.get(OWNER_SEARCH) == null) {
|
|
||||||
formData.addError(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"profile_site.owner.not_selected",
|
|
||||||
ProfileSiteConstants.BUNDLE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final ProfileSiteItem profileSiteItem = (ProfileSiteItem) super
|
|
||||||
.processBasicWidgets(event);
|
|
||||||
final FormData formData = event.getFormData();
|
|
||||||
final Person owner = (Person) formData.get(OWNER_SEARCH);
|
|
||||||
|
|
||||||
final ProfileSiteItemController controller = CdiUtil
|
|
||||||
.createCdiUtil()
|
|
||||||
.findBean(ProfileSiteItemController.class);
|
|
||||||
controller.setOwner(profileSiteItem.getObjectId(), owner.getObjectId());
|
|
||||||
|
|
||||||
init(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -18,17 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.librecms.profilesite;
|
package org.librecms.profilesite;
|
||||||
|
|
||||||
import com.arsdigita.cms.contenttypes.ui.ProfileSiteItemCreate;
|
|
||||||
import com.arsdigita.cms.contenttypes.ui.ProfileSiteItemInterestsStep;
|
|
||||||
import com.arsdigita.cms.contenttypes.ui.ProfileSiteItemMiscStep;
|
|
||||||
import com.arsdigita.cms.contenttypes.ui.ProfileSiteItemPositionStep;
|
|
||||||
import com.arsdigita.cms.contenttypes.ui.ProfileSiteItemPropertiesStep;
|
|
||||||
|
|
||||||
import org.libreccm.l10n.LocalizedString;
|
import org.libreccm.l10n.LocalizedString;
|
||||||
import org.librecms.assets.Person;
|
import org.librecms.assets.Person;
|
||||||
import org.librecms.contentsection.ContentItem;
|
import org.librecms.contentsection.ContentItem;
|
||||||
import org.librecms.contenttypes.AuthoringKit;
|
|
||||||
import org.librecms.contenttypes.AuthoringStep;
|
|
||||||
import org.librecms.contenttypes.ContentTypeDescription;
|
import org.librecms.contenttypes.ContentTypeDescription;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
@ -53,43 +46,6 @@ import static org.librecms.profilesite.ProfileSiteConstants.*;
|
||||||
labelBundle = "org.librecms.profilesite.ProfileSiteItem",
|
labelBundle = "org.librecms.profilesite.ProfileSiteItem",
|
||||||
descriptionBundle = "org.librecms.profilesite.ProfileSiteItem"
|
descriptionBundle = "org.librecms.profilesite.ProfileSiteItem"
|
||||||
)
|
)
|
||||||
@AuthoringKit(
|
|
||||||
createComponent = ProfileSiteItemCreate.class,
|
|
||||||
steps = {
|
|
||||||
@AuthoringStep(
|
|
||||||
component = ProfileSiteItemPropertiesStep.class,
|
|
||||||
labelBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
labelKey = "profile_site_item.basic_properties.label",
|
|
||||||
descriptionBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
descriptionKey = "profile_site_item.basic_properties.description",
|
|
||||||
order = 1
|
|
||||||
),
|
|
||||||
@AuthoringStep(
|
|
||||||
component = ProfileSiteItemPositionStep.class,
|
|
||||||
labelBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
labelKey = "profile_site_item.position.label",
|
|
||||||
descriptionBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
descriptionKey = "profile_site_item.position.description",
|
|
||||||
order = 2
|
|
||||||
),
|
|
||||||
@AuthoringStep(
|
|
||||||
component = ProfileSiteItemInterestsStep.class,
|
|
||||||
labelBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
labelKey = "profile_site_item.interests.label",
|
|
||||||
descriptionBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
descriptionKey = "profile_site_item.interests.description",
|
|
||||||
order = 3
|
|
||||||
),
|
|
||||||
@AuthoringStep(
|
|
||||||
component = ProfileSiteItemMiscStep.class,
|
|
||||||
labelBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
labelKey = "profile_site_item.misc.label",
|
|
||||||
descriptionBundle = ProfileSiteConstants.BUNDLE,
|
|
||||||
descriptionKey = "profile_site_item.misc.description",
|
|
||||||
order = 4
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public class ProfileSiteItem extends ContentItem {
|
public class ProfileSiteItem extends ContentItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
||||||
|
|
@ -123,11 +123,6 @@
|
||||||
<artifactId>jsoup</artifactId>
|
<artifactId>jsoup</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A central location for commonly used CMS services and their accessories.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <b>Context.</b> {@link #getContext()} fetches the context record ({@link
|
|
||||||
* com.arsdigita.kernel.KernelContext}) of the current thread.</p>
|
|
||||||
*
|
|
||||||
* @author Daniel Berrange
|
|
||||||
* @see com.arsdigita.kernel.Kernel
|
|
||||||
*/
|
|
||||||
public abstract class CMS {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The CMS XML namespace.
|
|
||||||
*/
|
|
||||||
public final static String CMS_XML_NS = "http://www.arsdigita.com/cms/1.0";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant string used as key for creating Workspace (content-center) as a
|
|
||||||
* legacy application.
|
|
||||||
*/
|
|
||||||
public static final String WORKSPACE_PACKAGE_KEY = "content-center";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant string used as key for creating service package as a legacy
|
|
||||||
* application.
|
|
||||||
*/
|
|
||||||
public final static String SERVICE_PACKAGE_KEY = "cms-service";
|
|
||||||
|
|
||||||
static final CMSContext s_initialContext = new CMSContext();
|
|
||||||
|
|
||||||
private static final ThreadLocal s_context = new ThreadLocal() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object initialValue() {
|
|
||||||
return s_initialContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the context record of the current thread.
|
|
||||||
*
|
|
||||||
* @post return != null
|
|
||||||
*/
|
|
||||||
public static final CMSContext getContext() {
|
|
||||||
return (CMSContext) s_context.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
static final void setContext(CMSContext context) {
|
|
||||||
s_context.set(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms;
|
|
||||||
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>The entry point into all the global state that CCM CMS code expects to
|
|
||||||
* have available to it when running, e.g. the current content section,
|
|
||||||
* current item
|
|
||||||
*
|
|
||||||
* <p>This is a session object that provides an environment in which
|
|
||||||
* code can execute. The CMSContext contains all session-specific
|
|
||||||
* variables. One session object is maintained per thread.</p>
|
|
||||||
*
|
|
||||||
* <p>Accessors of this class will assert that the item it returned is
|
|
||||||
* not null. If the caller wants to handle the case where an item is
|
|
||||||
* null explicitly, then use the hasContentItem and hasContentSection
|
|
||||||
* methods first.
|
|
||||||
*
|
|
||||||
* @see com.arsdigita.kernel.KernelContext
|
|
||||||
* @see com.arsdigita.cms.CMS
|
|
||||||
*
|
|
||||||
* @author Daniel Berrange
|
|
||||||
*/
|
|
||||||
public final class CMSContext {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(CMSContext.class);
|
|
||||||
|
|
||||||
private ContentSection m_section = null;
|
|
||||||
private ContentItem m_item = null;
|
|
||||||
private SecurityManager m_security = null;
|
|
||||||
|
|
||||||
CMSContext() {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String getDebugInfo() {
|
|
||||||
final String info = "Current state of " + this + ":\n" +
|
|
||||||
" getContentSection() -> " + getContentSection() + "\n" +
|
|
||||||
" getContentItem() -> " + getContentItem() + "\n" +
|
|
||||||
" getSecurityManager() -> " + getSecurityManager();
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
final CMSContext copy() {
|
|
||||||
final CMSContext result = new CMSContext();
|
|
||||||
|
|
||||||
result.m_section = m_section;
|
|
||||||
result.m_item = m_item;
|
|
||||||
result.m_security = m_security;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a content section is available
|
|
||||||
* @return true if a content section is available
|
|
||||||
*/
|
|
||||||
public final boolean hasContentSection() {
|
|
||||||
return m_section != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current content section
|
|
||||||
* not anymore: hasContentSection() == true
|
|
||||||
* @return the currently selected content section
|
|
||||||
*/
|
|
||||||
public final ContentSection getContentSection() {
|
|
||||||
// removing this which is not true when viewing category pages
|
|
||||||
//Assert.exists(m_section, "section");
|
|
||||||
return m_section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current content section
|
|
||||||
* @param section the new content section
|
|
||||||
*/
|
|
||||||
public final void setContentSection(final ContentSection section) {
|
|
||||||
m_section = section;
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Content section set to " + section);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a content item is available
|
|
||||||
* @return true if a content item is available
|
|
||||||
*/
|
|
||||||
public final boolean hasContentItem() {
|
|
||||||
return m_item != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current content item
|
|
||||||
* @pre hasContentItem() == true
|
|
||||||
* @return the current content item
|
|
||||||
*/
|
|
||||||
public final ContentItem getContentItem() {
|
|
||||||
// removing this which is necessarily true in ContentList
|
|
||||||
//Assert.exists(m_item, "item");
|
|
||||||
if (LOGGER.isDebugEnabled() && m_item == null) {
|
|
||||||
LOGGER.debug("Content item is null");
|
|
||||||
}
|
|
||||||
return m_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current content item
|
|
||||||
* @param item the new content item
|
|
||||||
*/
|
|
||||||
public final void setContentItem(final ContentItem item) {
|
|
||||||
m_item = item;
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Content item set to " + item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if there is a CMS <code>SecurityManager</code> for this
|
|
||||||
* session.
|
|
||||||
*
|
|
||||||
* @see com.arsdigita.cms.SecurityManager
|
|
||||||
* @return <code>true</code> if a security manager is available
|
|
||||||
*/
|
|
||||||
public final boolean hasSecurityManager() {
|
|
||||||
return m_security != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current security manager.
|
|
||||||
*
|
|
||||||
* @return the current security manager
|
|
||||||
*/
|
|
||||||
public final SecurityManager getSecurityManager() {
|
|
||||||
Assert.exists(m_security, SecurityManager.class);
|
|
||||||
|
|
||||||
return m_security;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setSecurityManager(final SecurityManager security) {
|
|
||||||
m_security = security;
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Security manager set to " + security);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms;
|
|
||||||
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ContentCenter extends CcmApplication {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 6672720141286517654L;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,307 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.cms.dispatcher.CMSPage;
|
|
||||||
import com.arsdigita.cms.ui.CMSApplicationPage;
|
|
||||||
import com.arsdigita.cms.ui.contentcenter.MainPage;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.kernel.security.Util;
|
|
||||||
import com.arsdigita.templating.PresentationManager;
|
|
||||||
import com.arsdigita.templating.Templating;
|
|
||||||
import com.arsdigita.ui.login.LoginHelper;
|
|
||||||
import com.arsdigita.web.ApplicationFileResolver;
|
|
||||||
import com.arsdigita.web.BaseApplicationServlet;
|
|
||||||
import com.arsdigita.web.LoginSignal;
|
|
||||||
import com.arsdigita.web.WebConfig;
|
|
||||||
import com.arsdigita.xml.Document;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.shiro.authz.AuthorizationException;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionRepository;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.RequestDispatcher;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.annotation.WebServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CMS ContentCenter (content-center) application servlet serves all request
|
|
||||||
* made within the Content Center application.
|
|
||||||
*
|
|
||||||
* @author Peter Boy <pboy@barkhof.uni-bremen.de>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@WebServlet(urlPatterns = "/content-center/*")
|
|
||||||
public class ContentCenterServlet extends BaseApplicationServlet {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 16543266935651171L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL (pathinfo) -> Page object mapping. Based on it (and the http request
|
|
||||||
* url) the doService method to selects a page to display
|
|
||||||
*/
|
|
||||||
private final Map<String, Page> pages = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to directory containg ccm-cms template files
|
|
||||||
*/
|
|
||||||
private String m_templatePath;
|
|
||||||
/**
|
|
||||||
* Resolvers to find templates (JSP) and other stuff stored in file system.
|
|
||||||
*/
|
|
||||||
private ApplicationFileResolver m_resolver;
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
ContentCenterServlet.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use parent's class initialisation extension point to perform additional
|
|
||||||
* initialisation tasks.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doInit() {
|
|
||||||
LOGGER.info("starting doInit method");
|
|
||||||
|
|
||||||
// NEW STUFF here used to process the pages in this servlet
|
|
||||||
// Addresses previously noted in WEB-INF/resources/content-center-map.xml
|
|
||||||
// Obviously not required.
|
|
||||||
|
|
||||||
|
|
||||||
addPage("/", new MainPage()); // index page at address ~/cc
|
|
||||||
addPage("/index", new MainPage());
|
|
||||||
|
|
||||||
|
|
||||||
// addPage("/item-search", new CMSItemSearchPage());
|
|
||||||
// Old style
|
|
||||||
//addPage("/item-search", new ItemSearchPage());
|
|
||||||
//addPage("/searchredirect", new CMSSearchResultRedirector());
|
|
||||||
|
|
||||||
// STUFF to use for JSP extension, i.e. jsp's to try for URLs which are not
|
|
||||||
// handled by the this servlet directly.
|
|
||||||
/**
|
|
||||||
* Set Template base path for JSP's
|
|
||||||
*/
|
|
||||||
// ToDo: Make it configurable by an appropriate config registry entry!
|
|
||||||
// m_templatePath = CMS.getConfig().getTemplateRoot();
|
|
||||||
m_templatePath = "/templates/ccm-cms/content-center";
|
|
||||||
/**
|
|
||||||
* Set TemplateResolver class
|
|
||||||
*/
|
|
||||||
m_resolver = WebConfig.getConfig().getResolver();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doService(final HttpServletRequest sreq,
|
|
||||||
final HttpServletResponse sresp,
|
|
||||||
final CcmApplication app) throws ServletException,
|
|
||||||
IOException {
|
|
||||||
LOGGER.info("starting doService method");
|
|
||||||
|
|
||||||
// ContentCenter workspace = (ContentCenter) app;
|
|
||||||
|
|
||||||
/* Check user and privilegies */
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
if (!shiro.getSubject().isAuthenticated()) {
|
|
||||||
throw new LoginSignal(sreq); // send to login page
|
|
||||||
}
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
final ContentSectionRepository sectionRepo = cdiUtil.findBean(
|
|
||||||
ContentSectionRepository.class);
|
|
||||||
final List<ContentSection> sections = sectionRepo.findAll();
|
|
||||||
boolean hasAccess = false;
|
|
||||||
for (final ContentSection section : sections) {
|
|
||||||
if (permissionChecker.isPermitted(ItemPrivileges.EDIT,
|
|
||||||
section.getRootDocumentsFolder())) {
|
|
||||||
hasAccess = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasAccess) { // user has no access privilege
|
|
||||||
throw new AuthorizationException(
|
|
||||||
"User is not entitled to access any content section");
|
|
||||||
// throw new LoginSignal(sreq); // send to login page
|
|
||||||
}
|
|
||||||
|
|
||||||
// New way to fetch the page
|
|
||||||
String pathInfo = sreq.getPathInfo();
|
|
||||||
if (pathInfo.length() > 1 && pathInfo.endsWith("/")) {
|
|
||||||
/* NOTE: ServletAPI specifies, pathInfo may be empty or will
|
|
||||||
* start with a '/' character. It currently carries a
|
|
||||||
* trailing '/' if a "virtual" page, i.e. not a real jsp, but
|
|
||||||
* result of a servlet mapping. But Application requires url
|
|
||||||
* NOT to end with a trailing '/' for legacy free applications. */
|
|
||||||
pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// An empty remaining URL or a URL which doesn't end in trailing slash:
|
|
||||||
// probably want to redirect.
|
|
||||||
// Probably DEPRECATED with new access method or only relevant for jsp
|
|
||||||
// extension
|
|
||||||
// if (m_trailingSlashList.contains(url) && !originalUrl.endsWith("/")) {
|
|
||||||
// DispatcherHelper.sendRedirect(sresp, originalUrl + "/");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
final Page page = pages.get(pathInfo);
|
|
||||||
if (page != null) {
|
|
||||||
|
|
||||||
// Check user access.
|
|
||||||
checkUserAccess(sreq, sresp);
|
|
||||||
|
|
||||||
if (page instanceof CMSPage) {
|
|
||||||
// backwards compatibility fix until migration completed
|
|
||||||
final CMSPage cmsPage = (CMSPage) page;
|
|
||||||
final RequestContext ctx = DispatcherHelper.getRequestContext();
|
|
||||||
cmsPage.init();
|
|
||||||
cmsPage.dispatch(sreq, sresp, ctx);
|
|
||||||
} else {
|
|
||||||
final CMSApplicationPage cmsAppPage = (CMSApplicationPage) page;
|
|
||||||
cmsAppPage.init(sreq, sresp, app);
|
|
||||||
// Serve the page.
|
|
||||||
final Document doc = cmsAppPage.buildDocument(sreq, sresp);
|
|
||||||
|
|
||||||
PresentationManager pm = Templating.getPresentationManager();
|
|
||||||
pm.servePage(doc, sreq, sresp);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Fall back on the JSP application dispatcher.
|
|
||||||
// NOTE: The JSP must ensure the proper authentication and
|
|
||||||
// authorisation if required!
|
|
||||||
LOGGER.info("NO page registered to serve the requst url.");
|
|
||||||
|
|
||||||
RequestDispatcher rd = m_resolver.resolve(m_templatePath,
|
|
||||||
sreq, sresp, app);
|
|
||||||
if (rd != null) {
|
|
||||||
LOGGER.debug("Got dispatcher " + rd);
|
|
||||||
|
|
||||||
final HttpServletRequest origreq = DispatcherHelper
|
|
||||||
.restoreOriginalRequest(sreq);
|
|
||||||
rd.forward(origreq, sresp);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
sresp.sendError(404, sreq.getRequestURI()
|
|
||||||
+ " not found on this server.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("doService method completed");
|
|
||||||
|
|
||||||
} // END doService()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal service mechod, adds one pair of Url - Page to the internal hash
|
|
||||||
* map, used as a cache.
|
|
||||||
*
|
|
||||||
* @param pathInfo url stub for a page to display
|
|
||||||
* @param page Page object to display
|
|
||||||
*/
|
|
||||||
private void addPage(final String pathInfo, final Page page) {
|
|
||||||
|
|
||||||
// Current Implementation requires pathInfo to start with a leading '/'
|
|
||||||
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
|
|
||||||
// with a '/' character."
|
|
||||||
pages.put(pathInfo, page);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Service Method returns the URL stub for the class name, can return null
|
|
||||||
// * if not mapped
|
|
||||||
// */
|
|
||||||
// // Currently still in use by c.ad.cms.ui.ItemSearchWidget
|
|
||||||
// public static String getURLStubForClass(String classname) {
|
|
||||||
// LOGGER.debug("Getting URL Stub for : " + classname);
|
|
||||||
// Iterator itr = s_pageURLs.keySet().iterator();
|
|
||||||
// while (itr.hasNext()) {
|
|
||||||
// String classname2 = (String) itr.next();
|
|
||||||
// s_log.debug("key: " + classname + " value: "
|
|
||||||
// + (String) s_pageURLs.get(classname2));
|
|
||||||
// }
|
|
||||||
// String url = (String) s_pageURLs.get(classname);
|
|
||||||
// return url;
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* Verify that the user is logged in and is able to view the page.
|
|
||||||
* Subclasses can override this method if they need to, but should always be
|
|
||||||
* sure to call super.checkUserAccess(...)
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @param response The HTTP response
|
|
||||||
* @param actx The request context
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void checkUserAccess(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response //,
|
|
||||||
/// final RequestContext actx
|
|
||||||
)
|
|
||||||
throws ServletException {
|
|
||||||
|
|
||||||
if (!CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject()
|
|
||||||
.isAuthenticated()) {
|
|
||||||
throw new LoginSignal(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirects the client to the login page, setting the return url to the
|
|
||||||
* current request URI.
|
|
||||||
*
|
|
||||||
* @exception ServletException If there is an exception thrown while trying
|
|
||||||
* to redirect, wrap that exception in a
|
|
||||||
* ServletException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void redirectToLoginPage(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp)
|
|
||||||
throws ServletException {
|
|
||||||
String url = Util.getSecurityHelper()
|
|
||||||
.getLoginURL(req)
|
|
||||||
+ "?" + LoginHelper.RETURN_URL_PARAM_NAME
|
|
||||||
+ "=" + DispatcherHelper.encodeReturnURL(req);
|
|
||||||
try {
|
|
||||||
LoginHelper.sendRedirect(req, resp, url);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.error("IO Exception", e);
|
|
||||||
throw new ServletException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.contenttypes.GenericAddress;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.domain.DomainObject;
|
|
||||||
import com.arsdigita.domain.DomainObjectTraversalAdapter;
|
|
||||||
import com.arsdigita.domain.DomainObjectXMLRenderer;
|
|
||||||
import com.arsdigita.globalization.GlobalizationHelper;
|
|
||||||
import com.arsdigita.persistence.metadata.Property;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a special ContentItemXMLRenderer for CMS to get a more transparent
|
|
||||||
* way to handle ContentBundles during XML output.
|
|
||||||
*
|
|
||||||
* The problem was to change RelatedLinks and therefore Link to always link to
|
|
||||||
* the corresponding ContentBundle instead of the content item. To get the
|
|
||||||
* corresponding content item during XML generation, I have to test for
|
|
||||||
* ContentBundle and negotiate the language version.
|
|
||||||
* This is not possible in com.arsdigita.ccm
|
|
||||||
*
|
|
||||||
* @author quasi
|
|
||||||
*/
|
|
||||||
public class ContentItemXMLRenderer extends DomainObjectXMLRenderer {
|
|
||||||
|
|
||||||
private static final Logger logger =
|
|
||||||
Logger.getLogger(ContentItemXMLRenderer.class);
|
|
||||||
private String m_propertyName = "";
|
|
||||||
private String m_keyName = "";
|
|
||||||
private String m_relationAttribute = "";
|
|
||||||
|
|
||||||
public ContentItemXMLRenderer(final Element root) {
|
|
||||||
super(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method will be called by DomainObjectTraversal.walk()
|
|
||||||
// It's purpose is to test for ContentBundle objects and if found, replace
|
|
||||||
// that object with the negotiated version of the content item.
|
|
||||||
// Otherwise this methd will do nothing.
|
|
||||||
@Override
|
|
||||||
protected void walk(final DomainObjectTraversalAdapter adapter,
|
|
||||||
final DomainObject obj,
|
|
||||||
final String path,
|
|
||||||
final String context,
|
|
||||||
final DomainObject linkObject) {
|
|
||||||
//final long start = System.nanoTime();
|
|
||||||
|
|
||||||
DomainObject nObj = obj;
|
|
||||||
|
|
||||||
if (nObj instanceof ContentBundle) {
|
|
||||||
|
|
||||||
nObj = ((ContentBundle) obj).getInstance(GlobalizationHelper.getNegotiatedLocale(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.walk(adapter, nObj, path, context, linkObject);
|
|
||||||
|
|
||||||
//System.out.printf("Walked object in %d ms\n", (System.nanoTime() - start) / 1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleAttribute(final DomainObject obj, final String path, final Property property) {
|
|
||||||
final String propertyName = property.getName();
|
|
||||||
|
|
||||||
// Special handling for the isoCountryCode field in GenericAddress
|
|
||||||
if (obj instanceof GenericAddress && "isoCountryCode".equals(propertyName)) {
|
|
||||||
//if (propertyName.equals("isoCountryCode")) {
|
|
||||||
super.handleAttribute(obj, path, property);
|
|
||||||
|
|
||||||
final Element element = newElement(m_element, "country");
|
|
||||||
element.setText(GenericAddress.getCountryNameFromIsoCode(((GenericAddress) obj).getIsoCountryCode()));
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special handling for the relation attribute keys
|
|
||||||
if (!m_relationAttribute.isEmpty()) {
|
|
||||||
String key = "";
|
|
||||||
|
|
||||||
// The RelationAttribute is part of this domain object as field
|
|
||||||
if (obj instanceof RelationAttributeInterface
|
|
||||||
&& ((RelationAttributeInterface) obj).
|
|
||||||
hasRelationAttributeProperty(propertyName)) {
|
|
||||||
|
|
||||||
final RelationAttributeInterface relationAttributeObject = (RelationAttributeInterface) obj;
|
|
||||||
key = relationAttributeObject.getRelationAttributeKey(
|
|
||||||
propertyName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// This RelationAttribute is part of an n:m association as link attribute
|
|
||||||
if (obj instanceof LinkDomainObject
|
|
||||||
&& propertyName.equals(m_keyName)) {
|
|
||||||
key = (String) ((LinkDomainObject) obj).get(m_keyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace value of the property defined in RELATION_ATTRIBUTES string
|
|
||||||
// of the primary domain object with the localized String.
|
|
||||||
if (!key.isEmpty()) {
|
|
||||||
// logger.debug(String.format(
|
|
||||||
// "Getting relation attribute value for key '%s' of relation attribute '%s'",
|
|
||||||
// key, m_relationAttribute));
|
|
||||||
final RelationAttributeCollection relationAttributeCollection = new RelationAttributeCollection(
|
|
||||||
m_relationAttribute, key);
|
|
||||||
relationAttributeCollection.addLanguageFilter(GlobalizationHelper.
|
|
||||||
getNegotiatedLocale().getLanguage());
|
|
||||||
if (!relationAttributeCollection.isEmpty()) {
|
|
||||||
relationAttributeCollection.next();
|
|
||||||
final Element element = newElement(m_element, m_keyName);
|
|
||||||
element.setText(relationAttributeCollection.getName());
|
|
||||||
final Element elementId = newElement(m_element, m_keyName + "Id");
|
|
||||||
elementId.setText(relationAttributeCollection.getKey());
|
|
||||||
relationAttributeCollection.close();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.handleAttribute(obj, path, property);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void beginAssociation(final DomainObject obj, final String path, final Property property) {
|
|
||||||
super.beginAssociation(obj, path, property);
|
|
||||||
|
|
||||||
final String propertyName = property.getName();
|
|
||||||
|
|
||||||
if (obj instanceof RelationAttributeInterface
|
|
||||||
&& ((RelationAttributeInterface) obj).hasRelationAttributeProperty(
|
|
||||||
propertyName)) {
|
|
||||||
|
|
||||||
final RelationAttributeInterface relationAttributeObject = (RelationAttributeInterface) obj;
|
|
||||||
|
|
||||||
m_propertyName = propertyName;
|
|
||||||
m_keyName = relationAttributeObject.getRelationAttributeKeyName(propertyName);
|
|
||||||
m_relationAttribute = relationAttributeObject.getRelationAttributeName(propertyName);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void endAssociation(final DomainObject obj, final String path, final Property property) {
|
|
||||||
|
|
||||||
m_propertyName = "";
|
|
||||||
m_keyName = "";
|
|
||||||
m_relationAttribute = "";
|
|
||||||
|
|
||||||
super.endAssociation(obj, path, property);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.parameters.LongParameter;
|
|
||||||
import com.arsdigita.ui.CcmObjectSelectionModel;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentType;
|
|
||||||
import org.librecms.contentsection.ContentTypeRepository;
|
|
||||||
import org.librecms.contenttypes.ContentTypeInfo;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Loads a subclass of a {@link com.arsdigita.cms.ContentItem} from the
|
|
||||||
* database. This model should be used as a parameter to the constructor of
|
|
||||||
* authoring kit components.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* It is possible to instantiate this model with a {@link
|
|
||||||
* com.arsdigita.cms.ContentType} as a constructor parameter. In this case, the
|
|
||||||
* model will only instantiate items that are of the specified content type, or
|
|
||||||
* one of it subclasses.</p>
|
|
||||||
*
|
|
||||||
* @author Stanislav Freidin (stas@arsdigita.com)
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*
|
|
||||||
* @see com.arsdigita.kernel.ui.ACSObjectSelectionModel
|
|
||||||
* @see com.arsdigita.bebop.SingleSelectionModel
|
|
||||||
*/
|
|
||||||
public class ItemSelectionModel extends CcmObjectSelectionModel<ContentItem> {
|
|
||||||
|
|
||||||
private Long typeId;
|
|
||||||
|
|
||||||
public ItemSelectionModel(final LongParameter parameter) {
|
|
||||||
super(ContentItem.class.getName(), parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSelectionModel(final String parameterName) {
|
|
||||||
super(ContentItem.class.getName(), parameterName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSelectionModel</code>
|
|
||||||
*
|
|
||||||
* @param type The content type for the items this model will
|
|
||||||
* generate
|
|
||||||
*
|
|
||||||
* @param parameterName The name of the state parameter which will be used
|
|
||||||
* to store the item.
|
|
||||||
*/
|
|
||||||
public ItemSelectionModel(final ContentType type,
|
|
||||||
final String parameterName) {
|
|
||||||
this(type, new LongParameter(parameterName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSelectionModel</code>
|
|
||||||
*
|
|
||||||
* @param type The content type for the items this model will generate
|
|
||||||
*
|
|
||||||
* @param parameter The state parameter which should be used by this item
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public ItemSelectionModel(final ContentType type,
|
|
||||||
final LongParameter parameter) {
|
|
||||||
super(type.getContentItemClass(), parameter);
|
|
||||||
typeId = type.getObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSelectionModel</code>
|
|
||||||
*
|
|
||||||
* @param type The content type for the items this model will generate
|
|
||||||
*
|
|
||||||
* @param model The {@link SingleSelectionModel} which will supply a
|
|
||||||
* {@link BigDecimal} id of the currently selected object
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public ItemSelectionModel(final ContentType type,
|
|
||||||
final SingleSelectionModel<Long> model) {
|
|
||||||
super(type.getContentItemClass(), model);
|
|
||||||
typeId = type.getObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSelectionModel(final ContentTypeInfo type,
|
|
||||||
final SingleSelectionModel<Long> model) {
|
|
||||||
super(type.getContentItemClass().getName(), model);
|
|
||||||
typeId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSelectionModel(final ContentTypeInfo type,
|
|
||||||
final LongParameter parameter) {
|
|
||||||
super(type.getContentItemClass().getName(), parameter);
|
|
||||||
typeId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience method that gets the currently selected object and casts it
|
|
||||||
* to a <code>ContentItem</code>
|
|
||||||
*
|
|
||||||
* @param state the current page state
|
|
||||||
*
|
|
||||||
* @return the currently selected <code>ContentItem</code>, or null if no
|
|
||||||
* item was selected.
|
|
||||||
*/
|
|
||||||
public final ContentItem getSelectedItem(final PageState state) {
|
|
||||||
return getSelectedObject(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return The content type of the items which are produced by this model,
|
|
||||||
* or null if the content type has not been specified in the
|
|
||||||
* constructor.
|
|
||||||
*/
|
|
||||||
public ContentType getContentType() {
|
|
||||||
|
|
||||||
ContentType type = null;
|
|
||||||
|
|
||||||
if (typeId != null) {
|
|
||||||
type = CdiUtil.createCdiUtil().findBean(ContentTypeRepository.class)
|
|
||||||
.findById(typeId).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the standard locations of the pages that comprise the
|
|
||||||
* content section user interface.
|
|
||||||
*
|
|
||||||
* @author Karl Goldstein (karlg at arsdigita dot com)
|
|
||||||
*
|
|
||||||
* @version $Id: PageLocations.java 2090 2010-04-17 08:04:14Z pboy $
|
|
||||||
**/
|
|
||||||
public interface PageLocations {
|
|
||||||
public String SECTION_PAGE = "admin/index.jsp";
|
|
||||||
public String ITEM_PAGE = "admin/item.jsp";
|
|
||||||
}
|
|
||||||
|
|
@ -1,718 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.ChainedDispatcher;
|
|
||||||
import com.arsdigita.dispatcher.Dispatcher;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.dispatcher.JSPApplicationDispatcher;
|
|
||||||
import com.arsdigita.dispatcher.RedirectException;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
import com.arsdigita.web.LoginSignal;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.shiro.authz.AuthorizationException;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.core.UnexpectedErrorException;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
|
||||||
import org.librecms.contentsection.ContentSectionRepository;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
import org.librecms.dispatcher.ItemResolver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* The CMS Dispatcher serves all request made within a content section. This
|
|
||||||
* dispatcher is called by the Subsite dispatcher.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Here are the steps for a request to
|
|
||||||
* <tt>http://yourserver/cms/cheese</tt> in excruciating detail:</p>
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li><p>
|
|
||||||
* A client sends a request to the web server, which passes it on to the global
|
|
||||||
* ACS dispatcher.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The global ACS dispatcher examines the first part of the URL, notices that
|
|
||||||
* CMS is mounted at <tt>/cms</tt> and hands the request to the CMS
|
|
||||||
* dispatcher.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The CMS dispatcher determines whether a <tt>Page</tt> has been registered to
|
|
||||||
* the URL <tt>/cheese</tt> in this section via its
|
|
||||||
* {@link com.arsdigita.cms.dispatcher.PageResolver}.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* Since no page is registered to the URL, the CMS dispatcher asks the content
|
|
||||||
* section (via its {@link com.arsdigita.cms.dispatcher.ItemResolver}) for a
|
|
||||||
* content item for <tt>/cheese</tt> in this content section. The result of this
|
|
||||||
* process is a {@link com.arsdigita.cms.ContentItem} object.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The CMS dispatcher asks the content section for a <tt>Page</tt>
|
|
||||||
* to use as the "master template" for this item. The content section may apply
|
|
||||||
* item-, type-, or request-specific rules to make this decision (for example,
|
|
||||||
* check a user preference for normal or accessible style, or a query parameter
|
|
||||||
* for a printable version).</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The CMS dispatcher hands the master <tt>Page</tt> object to the
|
|
||||||
* {@link com.arsdigita.sitenode.SiteNodePresentationManager} to serve the
|
|
||||||
* page.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The presentation manager asks the master <tt>Page</tt> object for an XML
|
|
||||||
* document representing the data for the page.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The master template begins walking through its component hierarchy,
|
|
||||||
* converting each component to XML by calling its
|
|
||||||
* <tt>generateXML</tt> method. The component responsible for rendering the
|
|
||||||
* content item uses an {@link com.arsdigita.cms.dispatcher.XMLGenerator} to
|
|
||||||
* convert the content item to XML.</p></li>
|
|
||||||
*
|
|
||||||
* <li><p>
|
|
||||||
* The presentation manager receives the completed XML document, and selects an
|
|
||||||
* XSL transformer to use for generating the HTML. The stylesheet on which the
|
|
||||||
* transformer is based contains templates for all styles and all content types
|
|
||||||
* in the content section, in particular those from the file
|
|
||||||
* <tt>cms-item.xsl</tt>.</p></li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @author Uday Mathur (umathur@arsdigita.com)
|
|
||||||
* @author Jack Chung (flattop@arsdigita.com)
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class CMSDispatcher implements Dispatcher, ChainedDispatcher {
|
|
||||||
|
|
||||||
private static Logger LOGGER = LogManager.getLogger(CMSDispatcher.class);
|
|
||||||
|
|
||||||
public static final String CONTENT_SECTION
|
|
||||||
= "com.arsdigita.cms.dispatcher.section";
|
|
||||||
|
|
||||||
public static final String CONTENT_ITEM
|
|
||||||
= "com.arsdigita.cms.dispatcher.item";
|
|
||||||
|
|
||||||
public static final String[] INDEX_FILES = {
|
|
||||||
"index.jsp", "index.html", "index.htm"};
|
|
||||||
|
|
||||||
private static final String DEBUG = "/debug";
|
|
||||||
private static final String ADMIN_SECTION = "admin";
|
|
||||||
|
|
||||||
public static final String ADMIN_URL = "admin/index";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The context for previewing items
|
|
||||||
*/
|
|
||||||
public static final String PREVIEW = "preview";
|
|
||||||
|
|
||||||
// Content section cache
|
|
||||||
private static HashMap s_pageResolverCache = new HashMap();
|
|
||||||
// private static HashMap s_itemResolverCache = new HashMap();
|
|
||||||
private static HashMap s_xmlGeneratorCache = new HashMap();
|
|
||||||
|
|
||||||
private boolean m_adminPagesOnly = false;
|
|
||||||
|
|
||||||
public CMSDispatcher() {
|
|
||||||
this(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSDispatcher(boolean adminOnly) {
|
|
||||||
m_adminPagesOnly = adminOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles requests made to a CMS package instance. 1) fetches the current
|
|
||||||
* content section 2) fetches the resource mapped to the current section/URL
|
|
||||||
* 3) if no resource, fetches the item associated with the current
|
|
||||||
* section/URL 4) if no item, passes request to the JSP dispatcher, which
|
|
||||||
* serves JSP's, HTML pages, and media from the cms/packages/www directory
|
|
||||||
*
|
|
||||||
* @param request The request
|
|
||||||
* @param response The response
|
|
||||||
* @param actx The request context
|
|
||||||
*/
|
|
||||||
public void dispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Dispatching request for " + new URL(request)
|
|
||||||
.toDebugString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the path to the current site node.
|
|
||||||
String processedUrl = actx.getProcessedURLPart();
|
|
||||||
String webappURLContext = request.getContextPath();
|
|
||||||
if (processedUrl.startsWith(webappURLContext)) {
|
|
||||||
processedUrl = processedUrl.substring(webappURLContext.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Determined the path to the current site node; it "
|
|
||||||
+ "is '" + processedUrl + "' according to the "
|
|
||||||
+ "request context");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the path within the site node.
|
|
||||||
String remainingUrl = actx.getRemainingURLPart();
|
|
||||||
if (remainingUrl.endsWith("/")) {
|
|
||||||
remainingUrl = remainingUrl.substring(0, remainingUrl.length() - 1);
|
|
||||||
} else if (remainingUrl.endsWith(ItemDispatcher.FILE_SUFFIX)) {
|
|
||||||
remainingUrl = remainingUrl.substring(0, remainingUrl.length()
|
|
||||||
- ItemDispatcher.FILE_SUFFIX
|
|
||||||
.length());
|
|
||||||
} else if (remainingUrl.equals("")) {
|
|
||||||
remainingUrl = "index";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Determined the path after the current site node; "
|
|
||||||
+ "it is '" + remainingUrl + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the current content section.
|
|
||||||
ContentSection section = null;
|
|
||||||
try {
|
|
||||||
section = findContentSection(processedUrl);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new ServletException(ex);
|
|
||||||
}
|
|
||||||
request.setAttribute(CONTENT_SECTION, section);
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Found content section '" + section + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check user access to this page and deny access if necessary.
|
|
||||||
checkUserAccess(request, response, actx);
|
|
||||||
|
|
||||||
// Look for a site-node-specific asset (if any).
|
|
||||||
// KG: This hack will be replaced by a ChainedDispatcher
|
|
||||||
try {
|
|
||||||
LOGGER.debug("Looking for a site node asset");
|
|
||||||
|
|
||||||
String siteNodeAssetURL = getSiteNodeAsset(request, actx);
|
|
||||||
if (siteNodeAssetURL != null) {
|
|
||||||
LOGGER.debug("Site node asset found at '" + siteNodeAssetURL
|
|
||||||
+ "'");
|
|
||||||
|
|
||||||
DispatcherHelper.cacheDisable(response);
|
|
||||||
DispatcherHelper.setRequestContext(request, actx);
|
|
||||||
DispatcherHelper.forwardRequestByPath(siteNodeAssetURL,
|
|
||||||
request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.debug("No site node asset found; proceeding with normal "
|
|
||||||
+ "dispatching");
|
|
||||||
} catch (RedirectException e) {
|
|
||||||
throw new ServletException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the requested resource (if any).
|
|
||||||
ResourceHandler resource = getResource(section, remainingUrl);
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Got a resource '" + resource + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resource != null) {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Found resource '" + remainingUrl + "'; "
|
|
||||||
+ "dispatching to it");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("resource dispatch for " + remainingUrl);
|
|
||||||
// Found resource, now serve it.
|
|
||||||
// NB, ResouceHandler implementations should take care of caching options
|
|
||||||
resource.dispatch(request, response, actx);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("No resource found at '" + remainingUrl + "'; "
|
|
||||||
+ "searching for a previewable content item at "
|
|
||||||
+ "this path");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the remaining URL starts with "preview/", then try and
|
|
||||||
// preview this item. Otherwise look for the live item.
|
|
||||||
boolean preview = false;
|
|
||||||
if (remainingUrl.startsWith(PREVIEW)) {
|
|
||||||
remainingUrl = remainingUrl.substring(PREVIEW.length());
|
|
||||||
preview = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for published / previewable item.
|
|
||||||
ContentItem item = null;
|
|
||||||
|
|
||||||
// Check if the user has access to view public pages
|
|
||||||
final PermissionChecker permissionChecker = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(PermissionChecker.class);
|
|
||||||
|
|
||||||
if (permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.VIEW_PUBLISHED, item)) {
|
|
||||||
if (preview) {
|
|
||||||
item = getContentItem(section,
|
|
||||||
remainingUrl,
|
|
||||||
CMSDispatcher.PREVIEW);
|
|
||||||
} else {
|
|
||||||
item = getContentItem(section,
|
|
||||||
remainingUrl,
|
|
||||||
"live");
|
|
||||||
}
|
|
||||||
if (item != null) {
|
|
||||||
request.setAttribute(CONTENT_ITEM, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item != null) {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Found item " + item + "; serving it");
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatcherHelper.cacheDisable(response);
|
|
||||||
preview(request, response, actx);
|
|
||||||
} else {
|
|
||||||
LOGGER.debug("No item to preview found; falling back to "
|
|
||||||
+ "JSP dispatcher to look for some concrete "
|
|
||||||
+ "resource in the file system");
|
|
||||||
|
|
||||||
// If no resource was found, look for a JSP page.
|
|
||||||
JSPApplicationDispatcher jsp = JSPApplicationDispatcher
|
|
||||||
.getInstance();
|
|
||||||
//DispatcherHelper.cacheDisable(response);
|
|
||||||
jsp.dispatch(request, response, actx);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public int chainedDispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
if (m_adminPagesOnly) {
|
|
||||||
String url = actx.getRemainingURLPart();
|
|
||||||
|
|
||||||
if (url.endsWith(ItemDispatcher.FILE_SUFFIX)) {
|
|
||||||
url = url.substring(0, url.length() - ItemDispatcher.FILE_SUFFIX
|
|
||||||
.length());
|
|
||||||
} else if (url.endsWith("/")) {
|
|
||||||
url = url.substring(0, url.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.equals(ADMIN_URL)) {
|
|
||||||
if (LOGGER.isInfoEnabled()) {
|
|
||||||
LOGGER.info("Resolving admin URL '" + url + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(request, response, actx);
|
|
||||||
|
|
||||||
return ChainedDispatcher.DISPATCH_BREAK;
|
|
||||||
} else {
|
|
||||||
return ChainedDispatcher.DISPATCH_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(request, response, actx);
|
|
||||||
return ChainedDispatcher.DISPATCH_BREAK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify that the user is logged in and is able to view the page.
|
|
||||||
* Subclasses can override this method if they need to, but should always be
|
|
||||||
* sure to call super.checkUserAccess(...)
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @param response The HTTP response
|
|
||||||
* @param actx The request context
|
|
||||||
*
|
|
||||||
* @throws javax.servlet.ServletException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void checkUserAccess(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws ServletException, AuthorizationException {
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
|
||||||
User user = shiro.getUser().get();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
|
|
||||||
ContentSection section = getContentSection(request);
|
|
||||||
|
|
||||||
if (isAdminPage(actx.getRemainingURLPart())) {
|
|
||||||
|
|
||||||
// Handle admin page requests.
|
|
||||||
// If the user is not logged in, redirect to the login page.
|
|
||||||
// Otherwise, perform the Admin Pages access check.
|
|
||||||
if (user == null) {
|
|
||||||
redirectToLoginPage(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//if (!sm.canAccess(user, SecurityManager.ADMIN_PAGES)) {
|
|
||||||
permissionChecker.checkPermission(ItemPrivileges.EDIT,
|
|
||||||
section.getRootDocumentsFolder());
|
|
||||||
} else {
|
|
||||||
// For public page requests, use the SecurityManager to check access
|
|
||||||
// SecurityManager.canAccess(user, SecurityManager.PUBLIC_PAGES) must
|
|
||||||
permissionChecker.checkPermission(
|
|
||||||
ItemPrivileges.VIEW_PUBLISHED,
|
|
||||||
section.getRootDocumentsFolder());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content section from the request attributes.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The content section
|
|
||||||
*
|
|
||||||
* @pre ( state != null )
|
|
||||||
*/
|
|
||||||
public static ContentSection getContentSection(HttpServletRequest request) {
|
|
||||||
return (ContentSection) request.getAttribute(CONTENT_SECTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content item from the request attributes.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The content item
|
|
||||||
*
|
|
||||||
* @pre ( state != null )
|
|
||||||
*/
|
|
||||||
public static ContentItem getContentItem(HttpServletRequest request) {
|
|
||||||
return (ContentItem) request.getAttribute(CONTENT_ITEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up the current content section using the remaining URL stored in
|
|
||||||
* the request context object and the SiteNode class.
|
|
||||||
*
|
|
||||||
* @param url The section URL stub
|
|
||||||
*
|
|
||||||
* @return The current Content Section
|
|
||||||
*/
|
|
||||||
protected ContentSection findContentSection(String url) {
|
|
||||||
|
|
||||||
// MP: This is a hack to get the debugging info in
|
|
||||||
// SiteNodePresentationManager.servePage, but since it's
|
|
||||||
// debugging info...
|
|
||||||
// Remove /debug from the start of the URL if it exists.
|
|
||||||
if (url.startsWith(DEBUG)) {
|
|
||||||
url = url.substring(DEBUG.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
final String debugXMLString = "/xml";
|
|
||||||
if (url.startsWith(debugXMLString)) {
|
|
||||||
url = url.substring(debugXMLString.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
final String debugXSLString = "/xsl";
|
|
||||||
if (url.startsWith(debugXSLString)) {
|
|
||||||
url = url.substring(debugXSLString.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
final String sectionLabel = url;
|
|
||||||
|
|
||||||
// Fetch the current site node from the URL.
|
|
||||||
final ContentSectionRepository sectionRepo = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(ContentSectionRepository.class);
|
|
||||||
final ContentSection section = sectionRepo
|
|
||||||
.findByLabel(url)
|
|
||||||
.orElseThrow(() -> new UnexpectedErrorException(
|
|
||||||
String.format("No ContentSection '%s' found.", sectionLabel)));
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch a resource based on the URL stub.
|
|
||||||
*
|
|
||||||
* @param section The current content section
|
|
||||||
* @param url The section-relative URL
|
|
||||||
*
|
|
||||||
* @return A ResourceHandler resource or null if none exists.
|
|
||||||
*
|
|
||||||
* @pre (url != null)
|
|
||||||
*/
|
|
||||||
protected ResourceHandler getResource(ContentSection section, String url)
|
|
||||||
throws ServletException {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Searching for a resource for the URL fragment '" + url
|
|
||||||
+ "' under " + section);
|
|
||||||
}
|
|
||||||
|
|
||||||
final PageResolver pageResolver = CMSDispatcher.getPageResolver(section);
|
|
||||||
|
|
||||||
final ResourceHandler handler = pageResolver.getPage(url);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup a content item by section and URL.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
* @param url The URL relative to the content section
|
|
||||||
* @param context The use context
|
|
||||||
*
|
|
||||||
* @return The item associated with the URL, or null if no such item exists
|
|
||||||
*
|
|
||||||
* @throws javax.servlet.ServletException
|
|
||||||
*/
|
|
||||||
protected ContentItem getContentItem(ContentSection section, String url,
|
|
||||||
String context)
|
|
||||||
throws ServletException {
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentSectionManager sectionManager = cdiUtil.findBean(
|
|
||||||
ContentSectionManager.class);
|
|
||||||
final ItemResolver itemResolver = sectionManager
|
|
||||||
.getItemResolver(section);
|
|
||||||
|
|
||||||
return itemResolver.getItem(section, url, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preview the current content item.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @param response The HTTP response
|
|
||||||
* @param actx The request context
|
|
||||||
*/
|
|
||||||
protected void preview(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
ContentSection section = getContentSection(request);
|
|
||||||
ContentItem item = getContentItem(request);
|
|
||||||
|
|
||||||
ItemResolver itemResolver = CMSDispatcher.getItemResolver(section);
|
|
||||||
CMSPage page = itemResolver.getMasterPage(item, request);
|
|
||||||
page.dispatch(request, response, actx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes the page resolver cache.
|
|
||||||
*
|
|
||||||
* @param section The current content section
|
|
||||||
* @param url The section-relative URL
|
|
||||||
*/
|
|
||||||
public static void releaseResource(ContentSection section, String url) {
|
|
||||||
final String pageResolverClassName = section.getPageResolverClass();
|
|
||||||
final PageResolver pageResolver;
|
|
||||||
try {
|
|
||||||
pageResolver = (PageResolver) Class.forName(pageResolverClassName)
|
|
||||||
.newInstance();
|
|
||||||
} catch (ClassNotFoundException
|
|
||||||
| IllegalAccessException
|
|
||||||
| InstantiationException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
pageResolver.releasePage(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the PageResolver for a content section. Checks cache first.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
*
|
|
||||||
* @return The PageResolver associated with the content section
|
|
||||||
*/
|
|
||||||
public static PageResolver getPageResolver(ContentSection section) {
|
|
||||||
LOGGER.debug("Getting the page resolver");
|
|
||||||
|
|
||||||
final String name = section.getLabel();
|
|
||||||
PageResolver pr = (PageResolver) s_pageResolverCache.get(name);
|
|
||||||
|
|
||||||
if (pr == null) {
|
|
||||||
LOGGER.debug("The page resolver was not cached; fetching a new "
|
|
||||||
+ "one and placing it in the cache");
|
|
||||||
|
|
||||||
final String pageResolverClassName = section.getPageResolverClass();
|
|
||||||
final PageResolver pageResolver;
|
|
||||||
try {
|
|
||||||
pageResolver = (PageResolver) Class.forName(
|
|
||||||
pageResolverClassName)
|
|
||||||
.newInstance();
|
|
||||||
} catch (ClassNotFoundException
|
|
||||||
| IllegalAccessException
|
|
||||||
| InstantiationException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
s_pageResolverCache.put(name, pageResolver);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the ItemResolver for a content section. Checks cache first.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
*
|
|
||||||
* @return The ItemResolver associated with the content section
|
|
||||||
*/
|
|
||||||
public static ItemResolver getItemResolver(ContentSection section) {
|
|
||||||
|
|
||||||
final Class<?> clazz;
|
|
||||||
try {
|
|
||||||
clazz = Class.forName(section.getItemResolverClass());
|
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
throw new UncheckedWrapperException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ItemResolver) CdiUtil.createCdiUtil().findBean(clazz);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the XMLGenerator for a content section. Checks cache first.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
*
|
|
||||||
* @return The XMLGenerator associated with the content section
|
|
||||||
*/
|
|
||||||
public static XMLGenerator getXMLGenerator(ContentSection section) {
|
|
||||||
String name = section.getLabel();
|
|
||||||
XMLGenerator xmlGenerator = (XMLGenerator) s_xmlGeneratorCache.get(name);
|
|
||||||
if (xmlGenerator == null) {
|
|
||||||
final String xmlGeneratorClassName = section.getXmlGeneratorClass();
|
|
||||||
try {
|
|
||||||
xmlGenerator = (XMLGenerator) Class.forName(
|
|
||||||
xmlGeneratorClassName).newInstance();
|
|
||||||
} catch (ClassNotFoundException
|
|
||||||
| IllegalAccessException
|
|
||||||
| InstantiationException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
s_xmlGeneratorCache.put(name, xmlGenerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
return xmlGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this URL correspond to an admin page?
|
|
||||||
*/
|
|
||||||
protected boolean isAdminPage(String url) {
|
|
||||||
|
|
||||||
// MP: This is a hack to get the debugging info in
|
|
||||||
// SiteNodePresentationManager.servePage, but since it's
|
|
||||||
// debugging info...
|
|
||||||
// Remove /debug from the start of the URL if it exists.
|
|
||||||
if (url.startsWith(DEBUG)) {
|
|
||||||
url = url.substring(DEBUG.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
return (url != null && (url.startsWith(ADMIN_SECTION) || url.startsWith(
|
|
||||||
PREVIEW)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirects the client to the login page, setting the return url to the
|
|
||||||
* current request URI.
|
|
||||||
*
|
|
||||||
* @exception ServletException If there is an exception thrown while trying
|
|
||||||
* to redirect, wrap that exception in a
|
|
||||||
* ServletException
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void redirectToLoginPage(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp)
|
|
||||||
throws ServletException {
|
|
||||||
throw new LoginSignal(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
// modified from JSPApplicationDispatcher
|
|
||||||
private String getSiteNodeAsset(HttpServletRequest request,
|
|
||||||
RequestContext actx)
|
|
||||||
throws RedirectException {
|
|
||||||
|
|
||||||
String siteNodeAssetURL = null;
|
|
||||||
|
|
||||||
ServletContext sctx = actx.getServletContext();
|
|
||||||
String processedURL = actx.getProcessedURLPart();
|
|
||||||
String remainingURL = actx.getRemainingURLPart();
|
|
||||||
// REMOVE THIS HACK ONCE we have working publish to file code in the build
|
|
||||||
//String templateRoot = PublishToFile.getDefaultDestinationForType(Template.class);
|
|
||||||
String templateRoot = null;
|
|
||||||
|
|
||||||
/* Allow a graceful early exit if publishToFile is not initialized */
|
|
||||||
if (null == templateRoot) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
File siteNodeAssetRoot = new File(templateRoot, processedURL);
|
|
||||||
File assetFile = new File(siteNodeAssetRoot, remainingURL);
|
|
||||||
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
|
|
||||||
if (assetFile.isDirectory()) {
|
|
||||||
|
|
||||||
if (remainingURL.endsWith("/")) {
|
|
||||||
throw new RedirectException(actx.getOriginalURL() + "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < INDEX_FILES.length; i++) {
|
|
||||||
File indexFile = new File(assetFile, INDEX_FILES[i]);
|
|
||||||
if (indexFile.exists()) {
|
|
||||||
assetFile = indexFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetFile.exists()) {
|
|
||||||
siteNodeAssetURL = contextPath + "/" + templateRoot
|
|
||||||
+ processedURL + remainingURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return siteNodeAssetURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,343 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BebopConfig;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.page.PageTransformer;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.templating.PresentationManager;
|
|
||||||
import com.arsdigita.web.Web;
|
|
||||||
import com.arsdigita.xml.Document;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentItemRepository;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionServlet;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A <tt>CMSPage</tt> is a Bebop {@link com.arsdigita.bebop.Page} implementation
|
|
||||||
* of the {@link com.arsdigita.cms.dispatcher.ResourceHandler} interface.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* It stores the current {@link com.arsdigita.cms.ContentSection} and, if
|
|
||||||
* applicable, the {@link com.arsdigita.cms.ContentItem} in the page state as
|
|
||||||
* request local objects. Components that are part of the <tt>CMSPage</tt>
|
|
||||||
* may access these objects by calling:</p>
|
|
||||||
* <blockquote><code><pre>
|
|
||||||
* getContentSection(PageState state);
|
|
||||||
* </pre></code></blockquote>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @author Uday Mathur (umathur@arsdigita.com)
|
|
||||||
*/
|
|
||||||
public class CMSPage extends Page implements ResourceHandler {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(CMSPage.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The global assets URL stub XML parameter name.
|
|
||||||
*/
|
|
||||||
public final static String ASSETS = "ASSETS";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The XML page class.
|
|
||||||
*/
|
|
||||||
public final static String PAGE_CLASS = "CMS";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map of XML parameters
|
|
||||||
*/
|
|
||||||
private HashMap m_params;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* */
|
|
||||||
private PageTransformer m_transformer;
|
|
||||||
|
|
||||||
public CMSPage() {
|
|
||||||
super();
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSPage(String title) {
|
|
||||||
super(title);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSPage(String title, Container panel) {
|
|
||||||
super(title, panel);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSPage(Label title) {
|
|
||||||
super(title);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSPage(Label title, Container panel) {
|
|
||||||
super(title, panel);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the page.
|
|
||||||
*/
|
|
||||||
protected void buildPage() {
|
|
||||||
// Set the class attribute value. May be overwritten by child class
|
|
||||||
// to hold a more specific value
|
|
||||||
setClassAttr(PAGE_CLASS);
|
|
||||||
|
|
||||||
// Global XML params.
|
|
||||||
// MP: This only works with older versions of Xalan.
|
|
||||||
m_params = new HashMap();
|
|
||||||
setXMLParameter(ASSETS, Utilities.getGlobalAssetsURL());
|
|
||||||
|
|
||||||
// MP: This is a hack to so that the XML params work with the newer
|
|
||||||
// version of Xalan.
|
|
||||||
// Sets attribute in SimpleComponent, attributes of the same name will
|
|
||||||
// be overweritten.
|
|
||||||
setAttribute(ASSETS, Utilities.getGlobalAssetsURL());
|
|
||||||
|
|
||||||
// Make sure the error display gets rendered.
|
|
||||||
getErrorDisplay().setIdAttr("page-body");
|
|
||||||
|
|
||||||
final Class<PresentationManager> presenterClass = BebopConfig
|
|
||||||
.getConfig().getPresenterClass();
|
|
||||||
final PresentationManager pm;
|
|
||||||
try {
|
|
||||||
pm = presenterClass.getDeclaredConstructor().newInstance();
|
|
||||||
} catch (InstantiationException
|
|
||||||
| IllegalAccessException
|
|
||||||
| InvocationTargetException
|
|
||||||
| NoSuchMethodException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pm instanceof PageTransformer) {
|
|
||||||
m_transformer = (PageTransformer) pm;
|
|
||||||
} else {
|
|
||||||
m_transformer = new PageTransformer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes and locks the page. If the page is already locked, does nothing.
|
|
||||||
*
|
|
||||||
* This method is called by the {@link com.arsdigita.dispatcher.Dispatcher}
|
|
||||||
* that initializes this page.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized void init() {
|
|
||||||
LOGGER.debug("Initializing the page");
|
|
||||||
|
|
||||||
if (!isLocked()) {
|
|
||||||
LOGGER.debug("The page hasn't been locked; locking it now");
|
|
||||||
|
|
||||||
lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the value of the XML parameter.
|
|
||||||
*
|
|
||||||
* @param name The parameter name
|
|
||||||
*
|
|
||||||
* @return The parameter value
|
|
||||||
*
|
|
||||||
* @pre (name != null)
|
|
||||||
*/
|
|
||||||
public String getXMLParameter(String name) {
|
|
||||||
return (String) m_params.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an XML parameter.
|
|
||||||
*
|
|
||||||
* @param name The parameter name
|
|
||||||
* @param value The parameter value
|
|
||||||
*
|
|
||||||
* @pre (name != null)
|
|
||||||
*/
|
|
||||||
public void setXMLParameter(String name, String value) {
|
|
||||||
m_params.put(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content section
|
|
||||||
*
|
|
||||||
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
|
|
||||||
* instead Despite of being deprecated it can not be removed because it is
|
|
||||||
* required by the interface Resourcehandler which is implemented by this
|
|
||||||
* class. On the other hand, if deprecated, implementing ResourceHandler may
|
|
||||||
* not be required
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ContentSection getContentSection(HttpServletRequest request) {
|
|
||||||
// Resets all content sections associations.
|
|
||||||
// return ContentSectionDispatcher.getContentSection(request);
|
|
||||||
return ContentSectionServlet.getContentSection(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return The current content section
|
|
||||||
*
|
|
||||||
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
|
|
||||||
* instead Despite of being deprecated it can not be removed because it is
|
|
||||||
* required by ContentItemPage which extends CMSPage and uses this method.
|
|
||||||
*/
|
|
||||||
public ContentSection getContentSection(PageState state) {
|
|
||||||
return getContentSection(state.getRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content item.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content item
|
|
||||||
*
|
|
||||||
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentItem()
|
|
||||||
* instead Despite of being deprecated it can not be removed because it is
|
|
||||||
* required by the interface Resourcehandler which is implemented by this
|
|
||||||
* class. On the other hand, if deprecated, implementing ResourceHandler may
|
|
||||||
* not be required
|
|
||||||
*/
|
|
||||||
public ContentItem getContentItem(HttpServletRequest request) {
|
|
||||||
// resets all content item associations
|
|
||||||
return ContentSectionDispatcher.getContentItem(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content item.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return The current content item
|
|
||||||
*
|
|
||||||
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentItem()
|
|
||||||
* instead. Despite of being deprecated it can not be removed because it is
|
|
||||||
* required by ContentItemPage which extends CMSPage and uses this method.
|
|
||||||
*/
|
|
||||||
public ContentItem getContentItem(PageState state) {
|
|
||||||
return getContentItem(state.getRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services the Bebop page.
|
|
||||||
*
|
|
||||||
* @param request The servlet request object
|
|
||||||
* @param response the servlet response object
|
|
||||||
* @param actx The request context
|
|
||||||
*
|
|
||||||
* @pre m_transformer != null
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void dispatch(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response,
|
|
||||||
final RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
final CcmApplication app = Web.getWebContext().getApplication();
|
|
||||||
ContentSection section = null;
|
|
||||||
|
|
||||||
if (app == null) {
|
|
||||||
//Nothing to do
|
|
||||||
} else if (app instanceof ContentSection) {
|
|
||||||
section = (ContentSection) app;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section != null) {
|
|
||||||
CMS.getContext().setContentSection(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String itemId = request.getParameter("item_id");
|
|
||||||
|
|
||||||
if (itemId != null) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
|
||||||
ContentItemRepository.class);
|
|
||||||
final ContentItem item = itemRepo
|
|
||||||
.findById(Long.parseLong(itemId)).get();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
permissionChecker.checkPermission(ItemPrivileges.PREVIEW,
|
|
||||||
item);
|
|
||||||
CMS.getContext().setContentItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Document document = buildDocument(request, response);
|
|
||||||
|
|
||||||
m_transformer.servePage(document, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwrites bebop.Page#generateXMLHelper to add the name of the user
|
|
||||||
* logged in to the page (displayed as part of the header).
|
|
||||||
*
|
|
||||||
* @param ps
|
|
||||||
* @param parent
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Element generateXMLHelper(PageState ps, Document parent) {
|
|
||||||
Element page = super.generateXMLHelper(ps, parent);
|
|
||||||
final Optional<User> user = CdiUtil.createCdiUtil()
|
|
||||||
.findBean(Shiro.class).getUser();
|
|
||||||
if (user.isPresent()) {
|
|
||||||
page.addAttribute("name", user.get().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,316 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.Dispatcher;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.web.Web;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the dispatcher for content-sections. It maintains a
|
|
||||||
* ContentItem-to-Template cache Code that modifies a published ContentItem's
|
|
||||||
* template must update the cache in this class by calling the appropriate cache
|
|
||||||
* methods.
|
|
||||||
*
|
|
||||||
* @author bche@redhat.com
|
|
||||||
*/
|
|
||||||
public class ContentItemDispatcher implements Dispatcher {
|
|
||||||
|
|
||||||
/** cache for the template resolver */
|
|
||||||
public static Map s_templateResolverCache = Collections
|
|
||||||
.synchronizedMap(new HashMap());
|
|
||||||
|
|
||||||
/** */
|
|
||||||
protected ItemXML m_itemXML;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* */
|
|
||||||
public ContentItemDispatcher() {
|
|
||||||
m_itemXML = new ItemXML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see com.arsdigita.dispatcher.Dispatcher#dispatch (HttpServletRequest,
|
|
||||||
* HttpServletResponse, RequestContext)
|
|
||||||
*/
|
|
||||||
public void dispatch(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response,
|
|
||||||
final RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
Boolean bXMLMode = (Boolean) request
|
|
||||||
.getAttribute("xmlMode");
|
|
||||||
if (bXMLMode != null && bXMLMode.booleanValue()) {
|
|
||||||
//if this is XML mode, then use itemXML
|
|
||||||
m_itemXML.dispatch(request, response, actx);
|
|
||||||
} else {
|
|
||||||
//this is normal dispatching
|
|
||||||
|
|
||||||
//get the Content Item
|
|
||||||
//final ContentItem item = (ContentItem) request.getAttribute
|
|
||||||
// (ContentSectionServlet.CONTENT_ITEM);
|
|
||||||
final ContentItem item = getContentItem(request);
|
|
||||||
//get the Content Section
|
|
||||||
final ContentSection section = (ContentSection) Web.getWebContext()
|
|
||||||
.getApplication();
|
|
||||||
|
|
||||||
Assert.exists(item);
|
|
||||||
|
|
||||||
//get the item's template
|
|
||||||
// final String sTemplateURL = getTemplatePath(item, request, actx);
|
|
||||||
|
|
||||||
//dispatch to the template
|
|
||||||
DispatcherHelper.setRequestContext(request, actx);
|
|
||||||
DispatcherHelper.forwardRequestByPath(null, request,
|
|
||||||
response);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content item from the request attributes.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The content item
|
|
||||||
*
|
|
||||||
* @pre ( request != null )
|
|
||||||
*/
|
|
||||||
public static ContentItem getContentItem(HttpServletRequest request) {
|
|
||||||
return (ContentItem) request.getAttribute(
|
|
||||||
"com.arsdigita.cms.dispatcher.item");
|
|
||||||
}
|
|
||||||
|
|
||||||
// //synchronize access to the cache
|
|
||||||
// private static synchronized void cachePut(BigDecimal contentItemID,
|
|
||||||
// String sTemplatePath) {
|
|
||||||
// s_cache.put(contentItemID, sTemplatePath);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static synchronized void cacheRemove(BigDecimal contentItemID) {
|
|
||||||
// s_cache.remove(contentItemID);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Method cacheRemove. Removes the cached template path for the contentItem
|
|
||||||
// * item
|
|
||||||
// *
|
|
||||||
// * @param item
|
|
||||||
// */
|
|
||||||
// public static void cacheRemove(ContentItem item) {
|
|
||||||
// if (item == null) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (s_log.isDebugEnabled()) {
|
|
||||||
// s_log.debug("removing cached entry for item " + item.getName()
|
|
||||||
// + " with ID " + item.getID());
|
|
||||||
// }
|
|
||||||
// s_cache.remove(item.getID());
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method cachePut. Maps the ContentItem item to the template t in the cache
|
|
||||||
*
|
|
||||||
* @param item
|
|
||||||
* @param t
|
|
||||||
*/
|
|
||||||
// public static void cachePut(ContentItem item, Template t) {
|
|
||||||
// ContentSection section = item.getContentSection();
|
|
||||||
// String sPath = getTemplatePath(section, t);
|
|
||||||
//
|
|
||||||
// //only cache live items
|
|
||||||
// if (item == null || item.getVersion().compareTo(ContentItem.LIVE) != 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (s_log.isDebugEnabled()) {
|
|
||||||
// s_log.debug("updating mapping for item " + item.getName()
|
|
||||||
// + " with ID " + item.getID() + " in section " + section
|
|
||||||
// .getName() + " of type " + item.getContentType().getName()
|
|
||||||
// + " to template " + sPath);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cachePut(item.getID(), sPath);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method cachePut. Maps all the content items of ContentType type and in
|
|
||||||
* ContentSection section that don't have their own templates to the
|
|
||||||
* template t in the cache
|
|
||||||
*
|
|
||||||
* @param section
|
|
||||||
* @param type
|
|
||||||
* @param t
|
|
||||||
*/
|
|
||||||
// public static void cachePut(ContentSection section,
|
|
||||||
// ContentType type,
|
|
||||||
// Template t) {
|
|
||||||
// s_log.debug("updating cache for section " + section.getName()
|
|
||||||
// + " and type " + type.getName());
|
|
||||||
//
|
|
||||||
// //get all the items in the section
|
|
||||||
// ItemCollection items = section.getItems();
|
|
||||||
//
|
|
||||||
// //filter items by content type
|
|
||||||
// BigDecimal typeID = type.getID();
|
|
||||||
// Filter filter = items.addFilter("type.id = :typeID");
|
|
||||||
// filter.set("typeID", typeID);
|
|
||||||
//
|
|
||||||
// //get only live items
|
|
||||||
// Filter liveFilter = items.addFilter("version = '" + ContentItem.LIVE
|
|
||||||
// + "'");
|
|
||||||
//
|
|
||||||
// //filter out content items in ContentSection section of
|
|
||||||
// //ContentType type with a template for the "public" context
|
|
||||||
// Filter itemsFilter = items.addNotInSubqueryFilter("id",
|
|
||||||
// "com.arsdigita.cms.ItemsWithTemplateMapping");
|
|
||||||
// itemsFilter.set("sectionId", section.getID());
|
|
||||||
// itemsFilter.set("typeId", type.getID());
|
|
||||||
//
|
|
||||||
// //TODO: FILTER OUT CONTENT ITEMS IN THIS SECTION OF THIS TYPE
|
|
||||||
// //WITH A TEMPLATE FOR THE "PUBLIC" CONTEXT
|
|
||||||
// /*
|
|
||||||
// * select items.item_id
|
|
||||||
// * from cms_items items, cms_item_template_map map
|
|
||||||
// * where items.item_id = map.item_id
|
|
||||||
// * and use_context = 'public'
|
|
||||||
// * and items.version = 'live'
|
|
||||||
// * and items.section_id = :section_id
|
|
||||||
// * and items.type_id = :type_id
|
|
||||||
// */
|
|
||||||
// synchronized (s_cache) {
|
|
||||||
// //update the cache for all items
|
|
||||||
// while (items.next()) {
|
|
||||||
// cachePut(items.getContentItem(), t);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private static String getTemplatePath(ContentSection section,
|
|
||||||
// Template template) {
|
|
||||||
// //the template path is
|
|
||||||
// // TEMPLATE_ROOT/[content-section-name]/[template-path]
|
|
||||||
// final String sep = java.io.File.separator;
|
|
||||||
// String sPath = ContentSectionConfig.getConfig().getTemplateRoot() + sep
|
|
||||||
// + section.getName() + sep + template.getPath();
|
|
||||||
// return sPath;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static void updateTemplateCache(ContentSection section,
|
|
||||||
// ContentItem item,
|
|
||||||
// String sTemplatePath) {
|
|
||||||
// //use the live version of the item for the cache
|
|
||||||
// item = item.getLiveVersion();
|
|
||||||
// s_log.debug("updating mapping for item " + item.getName() + " with ID "
|
|
||||||
// + item.getID() + " in section " + item.getContentSection()
|
|
||||||
// .getName() + " of type " + item.getContentType().getName()
|
|
||||||
// + " to template " + sTemplatePath);
|
|
||||||
// cachePut(item.getID(), sTemplatePath);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String cacheGet(BigDecimal key) {
|
|
||||||
// return (String) s_cache.get(key);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private String getTemplatePath(ContentItem item,
|
|
||||||
// HttpServletRequest req,
|
|
||||||
// RequestContext ctx) {
|
|
||||||
//
|
|
||||||
// //check if the template path is cached
|
|
||||||
// //BigDecimal id = item.getID();
|
|
||||||
// //String sPath = cacheGet(id);
|
|
||||||
// //return from cache
|
|
||||||
// // current cache scheme doesn't work when there are
|
|
||||||
// //multiple templates per item, as would happen with
|
|
||||||
// // multiple template contexts or in the case of
|
|
||||||
// //category item resolution, more than one category for
|
|
||||||
// //the item.
|
|
||||||
// //if (sPath != null) {
|
|
||||||
// //s_log.debug("returning template path from cache");
|
|
||||||
// // return sPath;
|
|
||||||
// //}
|
|
||||||
// //s_log.debug("template path not in cache, so fecthing");
|
|
||||||
// //template is not in the cache, so retrieve it and place it in
|
|
||||||
// //the cache
|
|
||||||
// String sPath = fetchTemplateURL(item, req, ctx);
|
|
||||||
// //cachePut(id, sPath);
|
|
||||||
//
|
|
||||||
// return sPath;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the URL of a template for an item. The returned URL is relative
|
|
||||||
* to the webapp context.
|
|
||||||
*/
|
|
||||||
// public String fetchTemplateURL(ContentItem item,
|
|
||||||
// HttpServletRequest request,
|
|
||||||
// RequestContext actx) {
|
|
||||||
// if (s_log.isDebugEnabled()) {
|
|
||||||
// s_log.debug("fetching URL for item " + item.getName() + " with ID "
|
|
||||||
// + item.getID());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ContentSection section = item.getContentSection();
|
|
||||||
// String templateURL = getTemplateResolver(section).getTemplate(section,
|
|
||||||
// item,
|
|
||||||
// request);
|
|
||||||
//
|
|
||||||
// if (s_log.isDebugEnabled()) {
|
|
||||||
// s_log.debug("templateURL is " + templateURL);
|
|
||||||
// }
|
|
||||||
// return templateURL;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Fetches the TemplateResolver for a content section. Checks cache first.
|
|
||||||
// *
|
|
||||||
// * @param section The content section
|
|
||||||
// *
|
|
||||||
// * @return The TemplateResolver associated with the content section
|
|
||||||
// */
|
|
||||||
// public TemplateResolver getTemplateResolver(ContentSection section) {
|
|
||||||
//
|
|
||||||
// String name = section.getName();
|
|
||||||
// TemplateResolver ir = (TemplateResolver) s_templateResolverCache.get(
|
|
||||||
// name);
|
|
||||||
//
|
|
||||||
// if (ir == null) {
|
|
||||||
// ir = section.getTemplateResolver();
|
|
||||||
// s_templateResolverCache.put(name, ir);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return ir;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionServlet;
|
|
||||||
import org.librecms.dispatcher.ItemResolver;
|
|
||||||
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This <code>ContentPanel</code> component fetches the
|
|
||||||
* {@link com.arsdigita.cms.dispatcher.XMLGenerator} for the content
|
|
||||||
* section.</p>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class ContentPanel extends SimpleComponent {
|
|
||||||
|
|
||||||
public ContentPanel() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches an XML Generator. This method can be overridden to fetch any
|
|
||||||
* {@link com.arsdigita.cms.dispatcher.XMLGenerator}, but by default, it
|
|
||||||
* fetches the <code>XMLGenerator</code> registered to the current
|
|
||||||
* {@link com.arsdigita.cms.ContentSection}.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return The XMLGenerator used by this Content Panel
|
|
||||||
*/
|
|
||||||
protected XMLGenerator getXMLGenerator(PageState state) {
|
|
||||||
ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
Assert.exists(section);
|
|
||||||
try {
|
|
||||||
return (XMLGenerator) Class.forName(section.getXmlGeneratorClass())
|
|
||||||
.newInstance();
|
|
||||||
} catch (ClassNotFoundException |
|
|
||||||
InstantiationException |
|
|
||||||
IllegalAccessException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates XML that represents a content item.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param parent The parent DOM element
|
|
||||||
*
|
|
||||||
* @see com.arsdigita.cms.dispatcher.XMLGenerator
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateXML(PageState state, Element parent) {
|
|
||||||
if (isVisible(state)) {
|
|
||||||
Element content = parent.newChildElement("cms:contentPanel",
|
|
||||||
CMS.CMS_XML_NS);
|
|
||||||
exportAttributes(content);
|
|
||||||
|
|
||||||
// Generate path information about the content item
|
|
||||||
generatePathInfoXML(state, content);
|
|
||||||
|
|
||||||
// Take advantage of caching in the CMS Dispatcher.
|
|
||||||
XMLGenerator xmlGenerator = getXMLGenerator(state);
|
|
||||||
|
|
||||||
xmlGenerator.generateXML(state, content, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate information about the path to this content item.
|
|
||||||
*
|
|
||||||
* @param state the page state
|
|
||||||
* @param parent the element that will contain the path info
|
|
||||||
*/
|
|
||||||
protected void generatePathInfoXML(PageState state, Element parent) {
|
|
||||||
Element pathInfo = parent
|
|
||||||
.newChildElement("cms:pathInfo", CMS.CMS_XML_NS);
|
|
||||||
|
|
||||||
if (CMS.getContext().hasContentSection()) {
|
|
||||||
pathInfo.newChildElement("cms:sectionPath", CMS.CMS_XML_NS).setText(
|
|
||||||
CMS.getContext().getContentSection().getPrimaryUrl());
|
|
||||||
}
|
|
||||||
String url = DispatcherHelper.getRequestContext().getRemainingURLPart();
|
|
||||||
if (url.startsWith(CMSDispatcher.PREVIEW)) {
|
|
||||||
pathInfo.newChildElement("cms:previewPath", CMS.CMS_XML_NS).setText(
|
|
||||||
ContentSectionServlet.PREVIEW);
|
|
||||||
}
|
|
||||||
pathInfo.newChildElement("cms:templatePrefix", CMS.CMS_XML_NS).setText(
|
|
||||||
"/" + ItemResolver.TEMPLATE_CONTEXT_PREFIX);
|
|
||||||
|
|
||||||
if (CMS.getContext().hasContentItem()) {
|
|
||||||
ContentItem item = CMS.getContext().getContentItem();
|
|
||||||
pathInfo.newChildElement("cms:itemPath", CMS.CMS_XML_NS).setText("/"
|
|
||||||
+ item.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.Dispatcher;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherChain;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.web.Web;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.web.ApplicationManager;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b><font color="red">Unsupported</font></b> Refactored content section
|
|
||||||
* dispatcher (under development).
|
|
||||||
*
|
|
||||||
* @author Karl Goldstein (karlg@arsdigita.com)
|
|
||||||
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class ContentSectionDispatcher implements Dispatcher {
|
|
||||||
|
|
||||||
public static final String CONTENT_ITEM
|
|
||||||
= "com.arsdigita.cms.dispatcher.item";
|
|
||||||
|
|
||||||
static final String CONTENT_SECTION = "com.arsdigita.cms.dispatcher.section";
|
|
||||||
|
|
||||||
private DispatcherChain dispatcherChain = new DispatcherChain();
|
|
||||||
|
|
||||||
public ContentSectionDispatcher() {
|
|
||||||
|
|
||||||
dispatcherChain.addChainedDispatcher(new CMSDispatcher(true));
|
|
||||||
dispatcherChain.addChainedDispatcher(new FileDispatcher());
|
|
||||||
dispatcherChain.addChainedDispatcher(new ItemDispatcher());
|
|
||||||
dispatcherChain.addChainedDispatcher(new CMSDispatcher());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext context)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
setContentSection(request, context);
|
|
||||||
dispatcherChain.dispatch(request, response, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content section from the request attributes.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The content section
|
|
||||||
*
|
|
||||||
* @pre ( request != null )
|
|
||||||
*/
|
|
||||||
public static ContentSection getContentSection(HttpServletRequest request) {
|
|
||||||
return (ContentSection) request.getAttribute(CONTENT_SECTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content item from the request attributes.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The content item
|
|
||||||
*
|
|
||||||
* @pre ( request != null )
|
|
||||||
*/
|
|
||||||
public static ContentItem getContentItem(HttpServletRequest request) {
|
|
||||||
return (ContentItem) request.getAttribute(CONTENT_ITEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up the current content section using the remaining URL stored in
|
|
||||||
* the request context object and the SiteNode class.
|
|
||||||
*
|
|
||||||
* @param url The section URL stub
|
|
||||||
*
|
|
||||||
* @return The current Content Section
|
|
||||||
*/
|
|
||||||
private void setContentSection(HttpServletRequest request,
|
|
||||||
// SiteNodeRequestContext actx)
|
|
||||||
RequestContext actx)
|
|
||||||
throws ServletException {
|
|
||||||
|
|
||||||
final ContentSection section = (ContentSection) Web.getWebContext()
|
|
||||||
.getApplication();
|
|
||||||
request.setAttribute(CONTENT_SECTION, section);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that the current user has permission to access the admin pages.
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param section
|
|
||||||
*/
|
|
||||||
public static boolean checkAdminAccess(HttpServletRequest request,
|
|
||||||
ContentSection section) {
|
|
||||||
|
|
||||||
return CdiUtil.createCdiUtil().findBean(PermissionChecker.class)
|
|
||||||
.isPermitted(ItemPrivileges.EDIT, section
|
|
||||||
.getRootDocumentsFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ContentItem;
|
|
||||||
import com.arsdigita.cms.ContentSection;
|
|
||||||
import com.arsdigita.cms.ContentType;
|
|
||||||
import com.arsdigita.cms.Folder;
|
|
||||||
import com.arsdigita.cms.Template;
|
|
||||||
import com.arsdigita.cms.TemplateManager;
|
|
||||||
import com.arsdigita.cms.TemplateManagerFactory;
|
|
||||||
import com.arsdigita.mimetypes.MimeType;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ------- May be outdated. TemplateResolver has been reworked. ----------
|
|
||||||
* Resolves the JSP template to use for dispatching an
|
|
||||||
* item. This replaces TemplateResolver since the latter
|
|
||||||
* has a useless API.
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* <p>In general, the process for resolving a template involves two
|
|
||||||
* steps:</p>
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
*
|
|
||||||
* <li>The template resolver examines specific properties of the
|
|
||||||
* item, the content section, and/or the request itself and selects
|
|
||||||
* an appropriate <em>context</em>. A context is simply a token
|
|
||||||
* such as "plain" or "fancy".
|
|
||||||
*
|
|
||||||
* <li>Based on the selected context, the template resolver
|
|
||||||
* identifies an appropriate template for the item. This is a
|
|
||||||
* three-step process: (1) the resolver queries for an association
|
|
||||||
* between the item and a specific template for the selected
|
|
||||||
* context; (2) if no such association exists, the resolver queries
|
|
||||||
* the item's content type for a default template to use in the
|
|
||||||
* selected context; (3) if a default template is not found, return
|
|
||||||
* null (at which point the dispatcher should probably give up and
|
|
||||||
* return a 404 error).
|
|
||||||
*
|
|
||||||
* </ol>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class DefaultTemplateResolver extends AbstractTemplateResolver
|
|
||||||
implements TemplateResolver {
|
|
||||||
|
|
||||||
private static Logger s_log = Logger.getLogger(DefaultTemplateResolver.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JSP template filename relative to the webapp
|
|
||||||
* root.
|
|
||||||
*
|
|
||||||
* @param section The ContentSection for the request
|
|
||||||
* @param item The ContentItem for the request
|
|
||||||
* @param request The current HttpServletRequest
|
|
||||||
*
|
|
||||||
* @return The path to the jsp template.
|
|
||||||
*/
|
|
||||||
public String getTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
|
|
||||||
String template = getItemTemplate(section, item, request);
|
|
||||||
MimeType mimeType = MimeType.loadMimeType(Template.JSP_MIME_TYPE);
|
|
||||||
|
|
||||||
if (template == null) {
|
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("No item template, looking for content type template");
|
|
||||||
}
|
|
||||||
template = getTypeTemplate(section, item, request, mimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (template == null) {
|
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("No content type template, looking for default template");
|
|
||||||
}
|
|
||||||
|
|
||||||
template = getDefaultTemplate(section, item, request);
|
|
||||||
|
|
||||||
Assert.exists(template, "default template");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_log.isInfoEnabled()) {
|
|
||||||
s_log.info("Got template " + template + " for item " + item.getOID());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ContentSection.getConfig().getTemplateRoot() + template;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JSP template filename relative to the webapp
|
|
||||||
* root for a given Template reference.
|
|
||||||
*
|
|
||||||
* @param template The Template to resolve the URL for.
|
|
||||||
*
|
|
||||||
* @return The path to the jsp template.
|
|
||||||
*/
|
|
||||||
public String getTemplatePath(Template template) {
|
|
||||||
|
|
||||||
return ContentSection.getConfig().getTemplateRoot() +
|
|
||||||
getTemplateFilename(template, template.getContentSection());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the XSL template filename relative to the webapp
|
|
||||||
* root for a given Template reference.
|
|
||||||
*
|
|
||||||
* @param template The Template to resolve the URL for.
|
|
||||||
*
|
|
||||||
* @return The path to the xsl template.
|
|
||||||
*/
|
|
||||||
public String getTemplateXSLPath(Template template) {
|
|
||||||
|
|
||||||
return ContentSection.getConfig().getTemplateRoot() +
|
|
||||||
getTemplateXSLFilename(template, template.getContentSection());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the template associated with the item (if any)
|
|
||||||
*/
|
|
||||||
protected String getItemTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
TemplateManager manager = TemplateManagerFactory.getInstance();
|
|
||||||
String context = getTemplateContext(request);
|
|
||||||
Template template = manager.getTemplate(item, context);
|
|
||||||
|
|
||||||
return template == null ? null : getTemplateFilename(
|
|
||||||
template, section
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the template associated with the type (if any)
|
|
||||||
* @deprecated Use the version that specifies a mime type
|
|
||||||
*/
|
|
||||||
protected String getTypeTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
MimeType mimeType = MimeType.loadMimeType(Template.JSP_MIME_TYPE);
|
|
||||||
return getTypeTemplate(section, item, request, mimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the template associated with the type (if any)
|
|
||||||
*/
|
|
||||||
protected String getTypeTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request,
|
|
||||||
MimeType mimeType) {
|
|
||||||
TemplateManager manager = TemplateManagerFactory.getInstance();
|
|
||||||
ContentType type = item.getContentType();
|
|
||||||
|
|
||||||
Template template = null;
|
|
||||||
|
|
||||||
if (type != null ) {
|
|
||||||
String context = getTemplateContext(request);
|
|
||||||
template = manager.getDefaultTemplate(section, type, context, mimeType);
|
|
||||||
} else {
|
|
||||||
if (s_log.isDebugEnabled()) {
|
|
||||||
s_log.debug("Item has no content type, not looking for a " +
|
|
||||||
"content type specific template");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return template == null ? null : getTemplateFilename(
|
|
||||||
template, section
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the default template
|
|
||||||
*/
|
|
||||||
protected String getDefaultTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
String path = (item instanceof Folder) ?
|
|
||||||
ContentSection.getConfig().getDefaultFolderTemplatePath() :
|
|
||||||
ContentSection.getConfig().getDefaultItemTemplatePath();
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the filename for a Template object
|
|
||||||
*/
|
|
||||||
protected String getTemplateFilename(Template template,
|
|
||||||
ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
return getTemplateFilename(template, section);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the filename for a Template object
|
|
||||||
*/
|
|
||||||
protected String getTemplateXSLFilename(Template template,
|
|
||||||
ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request) {
|
|
||||||
return getTemplateXSLFilename(template, section);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the filename for a Template object
|
|
||||||
*/
|
|
||||||
protected String getTemplateFilename(Template template,
|
|
||||||
ContentSection section) {
|
|
||||||
|
|
||||||
String templateName = template.getPath();
|
|
||||||
String sectionURL = section.getPath();
|
|
||||||
return sectionURL + "/" + templateName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the filename for a Template object
|
|
||||||
*/
|
|
||||||
protected String getTemplateXSLFilename(Template template,
|
|
||||||
ContentSection section) {
|
|
||||||
|
|
||||||
String templateName = template.getPathNoJsp() + ".xsl";
|
|
||||||
String sectionURL = section.getPath();
|
|
||||||
|
|
||||||
return sectionURL + "/" + templateName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.ChainedDispatcher;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches to a file stored under the CMS package root
|
|
||||||
* (<code>/packages/cms/www</code>). This includes both unmanaged files copied
|
|
||||||
* or created directly in the file system, as well as pages and assets published
|
|
||||||
* to the file system from CMS.
|
|
||||||
*
|
|
||||||
* @author Karl Goldstein (karlg@arsdigita.com)
|
|
||||||
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id$
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FileDispatcher implements ChainedDispatcher {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
ChainedDispatcher.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int chainedDispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext context)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
File jspFile = getPackageFile(context);
|
|
||||||
|
|
||||||
if (jspFile.exists() && !jspFile.isDirectory()) {
|
|
||||||
String packageURL = context.getPageBase() + context
|
|
||||||
.getRemainingURLPart();
|
|
||||||
LOGGER.debug("DISPATCHING to " + packageURL);
|
|
||||||
|
|
||||||
// don't match folders, since they don't actually match a file
|
|
||||||
if (!packageURL.endsWith("/")) {
|
|
||||||
LOGGER.debug("DISPATCHING to " + packageURL);
|
|
||||||
// Don't set caching headers - let JSP file do it if required
|
|
||||||
//DispatcherHelper.maybeCacheDisable(response);
|
|
||||||
DispatcherHelper.setRequestContext(request, context);
|
|
||||||
DispatcherHelper.forwardRequestByPath(packageURL, request,
|
|
||||||
response);
|
|
||||||
return ChainedDispatcher.DISPATCH_BREAK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChainedDispatcher.DISPATCH_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches the request URL to a file in the package www directory.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private File getPackageFile(RequestContext appContext) {
|
|
||||||
|
|
||||||
ServletContext servletContext = appContext.getServletContext();
|
|
||||||
|
|
||||||
String filePath = appContext.getRemainingURLPart();
|
|
||||||
|
|
||||||
String packageDocRoot = servletContext.getRealPath(appContext
|
|
||||||
.getPageBase());
|
|
||||||
|
|
||||||
File jspFile = new File(packageDocRoot, filePath);
|
|
||||||
|
|
||||||
return jspFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,289 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.ChainedDispatcher;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.web.LoginSignal;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
|
||||||
import org.librecms.contentsection.ContentSectionServlet;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
import org.librecms.dispatcher.ItemResolver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches to the JSP or Servlet for rendering a content item.
|
|
||||||
*
|
|
||||||
* @author Karl Goldstein (karlg@arsdigita.com)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ItemDispatcher implements ChainedDispatcher {
|
|
||||||
|
|
||||||
private static Logger LOGGER = LogManager.getLogger(ItemDispatcher.class);
|
|
||||||
|
|
||||||
public static Map s_itemResolverCache = Collections.synchronizedMap(
|
|
||||||
new HashMap());
|
|
||||||
public static Map s_templateResolverCache = Collections.synchronizedMap(
|
|
||||||
new HashMap());
|
|
||||||
|
|
||||||
public static final String FILE_SUFFIX = ".jsp";
|
|
||||||
public static final String INDEX_FILE = "/index";
|
|
||||||
// public static final String TEMPLATE_ROOT =
|
|
||||||
// "/packages/content-section/templates";
|
|
||||||
// public static final String DEFAULT_ITEM_TEMPLATE = "/default/item.jsp";
|
|
||||||
// public static final String DEFAULT_FOLDER_TEMPLATE = "/default/folder.jsp";
|
|
||||||
|
|
||||||
public static final String XML_SUFFIX = ".xml";
|
|
||||||
public static final String XML_MODE = "xmlMode";
|
|
||||||
|
|
||||||
private static boolean m_cacheItems = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The context for previewing items
|
|
||||||
*/
|
|
||||||
public static final String PREVIEW = "/preview";
|
|
||||||
|
|
||||||
protected ItemXML m_itemXML;
|
|
||||||
|
|
||||||
public ItemDispatcher() {
|
|
||||||
super();
|
|
||||||
m_itemXML = new ItemXML();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setCacheItems(boolean value) {
|
|
||||||
m_cacheItems = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int chainedDispatch(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response,
|
|
||||||
final RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
String queryString = request.getQueryString();
|
|
||||||
String url = actx.getRemainingURLPart();
|
|
||||||
|
|
||||||
LOGGER.info("Resolving item URL " + url);
|
|
||||||
|
|
||||||
if (url.endsWith(XML_SUFFIX)) {
|
|
||||||
request.setAttribute(XML_MODE, Boolean.TRUE);
|
|
||||||
LOGGER.debug("StraightXML Requested");
|
|
||||||
url = "/" + url.substring(0, url.length() - XML_SUFFIX.length());
|
|
||||||
} else {
|
|
||||||
request.setAttribute(XML_MODE, Boolean.FALSE);
|
|
||||||
// it's neither a .jsp or a .xml, thus its an error
|
|
||||||
if (url.endsWith(FILE_SUFFIX)) {
|
|
||||||
url = "/" + url
|
|
||||||
.substring(0, url.length() - FILE_SUFFIX.length());
|
|
||||||
} else if (url.endsWith("/")) {
|
|
||||||
url = "/" + url.substring(0, url.length() - 1);
|
|
||||||
} else {
|
|
||||||
LOGGER.warn("Fail: URL doesn't have right suffix.");
|
|
||||||
return ChainedDispatcher.DISPATCH_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ContentSection section = ContentSectionServlet.getContentSection(
|
|
||||||
request);
|
|
||||||
// ContentSectionDispatcher.getContentSection(request);
|
|
||||||
|
|
||||||
final ContentItem item = getItem(section, url);
|
|
||||||
if (item == null) {
|
|
||||||
LOGGER.warn("Fail: No live item found matching " + url);
|
|
||||||
return ChainedDispatcher.DISPATCH_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.setAttribute(ContentSectionDispatcher.CONTENT_ITEM, item);
|
|
||||||
|
|
||||||
LOGGER.debug("MATCHED " + item.getObjectId());
|
|
||||||
|
|
||||||
// Work out how long to cache for....
|
|
||||||
// We take minimum(default timeout, lifecycle expiry)
|
|
||||||
//ToDo
|
|
||||||
// Lifecycle cycle = item.getLifecycle();
|
|
||||||
int expires = DispatcherHelper.getDefaultCacheExpiry();
|
|
||||||
// if (cycle != null) {
|
|
||||||
// Date endDate = cycle.getEndDate();
|
|
||||||
//
|
|
||||||
// if (endDate != null) {
|
|
||||||
// int maxAge = (int) ( ( endDate.getTime() - System.currentTimeMillis() ) / 1000l );
|
|
||||||
// if (maxAge < expires) {
|
|
||||||
// expires = maxAge;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//ToDo end
|
|
||||||
// NB, this is not the same as the security check previously
|
|
||||||
// We are checking if anyone can access - ie can we allow
|
|
||||||
// this page to be publically cached
|
|
||||||
if (m_cacheItems && !url.startsWith(PREVIEW)) {
|
|
||||||
// if (sm.canAccess((User)null, SecurityManager.PUBLIC_PAGES, item)) {
|
|
||||||
if (CdiUtil.createCdiUtil().findBean(PermissionChecker.class)
|
|
||||||
.isPermitted(
|
|
||||||
ItemPrivileges.VIEW_PUBLISHED, item)) {
|
|
||||||
DispatcherHelper.cacheForWorld(response, expires);
|
|
||||||
} else {
|
|
||||||
DispatcherHelper.cacheForUser(response, expires);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DispatcherHelper.cacheDisable(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((Boolean) request.getAttribute(XML_MODE)).booleanValue()) {
|
|
||||||
m_itemXML.dispatch(request, response, actx);
|
|
||||||
return ChainedDispatcher.DISPATCH_BREAK;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// normal dispatching
|
|
||||||
// This part assumes the template is JSP.
|
|
||||||
// final String templateURL = getTemplateURL(section, item, request,
|
|
||||||
// actx);
|
|
||||||
// s_log.debug("TEMPLATE " + templateURL);
|
|
||||||
DispatcherHelper.setRequestContext(request, actx);
|
|
||||||
DispatcherHelper.forwardRequestByPath(null, request,
|
|
||||||
response);
|
|
||||||
return ChainedDispatcher.DISPATCH_BREAK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContentItem getItem(ContentSection section, String url) {
|
|
||||||
|
|
||||||
ItemResolver itemResolver = getItemResolver(section);
|
|
||||||
ContentItem item;
|
|
||||||
// Check if the user has access to view public or preview pages
|
|
||||||
boolean hasPermission = true;
|
|
||||||
HttpServletRequest request = DispatcherHelper.getRequest();
|
|
||||||
|
|
||||||
// If the remaining URL starts with "preview/", then try and
|
|
||||||
// preview this item. Otherwise look for the live item.
|
|
||||||
boolean preview = false;
|
|
||||||
if (url.startsWith(PREVIEW)) {
|
|
||||||
url = url.substring(PREVIEW.length());
|
|
||||||
preview = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
|
|
||||||
if (preview) {
|
|
||||||
item = itemResolver.getItem(section, url, "draft");
|
|
||||||
if (item != null) {
|
|
||||||
hasPermission = permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.PREVIEW, item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item = itemResolver.getItem(section, url, "live");
|
|
||||||
if (item != null) {
|
|
||||||
hasPermission = permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.VIEW_PUBLISHED, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item == null && url.endsWith(INDEX_FILE)) {
|
|
||||||
|
|
||||||
// look up folder if it's an index
|
|
||||||
url = url.substring(0, url.length() - INDEX_FILE.length());
|
|
||||||
LOGGER.info("Attempting to match folder " + url);
|
|
||||||
item = itemResolver.getItem(section, url, "live");
|
|
||||||
if (item != null) {
|
|
||||||
hasPermission = permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.VIEW_PUBLISHED, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// chris.gilbert@westsussex.gov.uk - if user is not logged in, give them a chance to do that, else show them the door
|
|
||||||
if (!hasPermission && !cdiUtil.findBean(Shiro.class).getSubject()
|
|
||||||
.isAuthenticated()) {
|
|
||||||
throw new LoginSignal(request);
|
|
||||||
}
|
|
||||||
if (!hasPermission) {
|
|
||||||
throw new com.arsdigita.dispatcher.AccessDeniedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the ItemResolver for a content section.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
*
|
|
||||||
* @return The ItemResolver associated with the content section
|
|
||||||
*/
|
|
||||||
public ItemResolver getItemResolver(ContentSection section) {
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentSectionManager sectionManager = cdiUtil.findBean(
|
|
||||||
ContentSectionManager.class);
|
|
||||||
|
|
||||||
return sectionManager.getItemResolver(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the ItemResolver for a content section. Checks cache first.
|
|
||||||
*
|
|
||||||
* @param section The content section
|
|
||||||
*
|
|
||||||
* @return The ItemResolver associated with the content section
|
|
||||||
*/
|
|
||||||
// public TemplateResolver getTemplateResolver(ContentSection section) {
|
|
||||||
//
|
|
||||||
// String name = section.getName();
|
|
||||||
// TemplateResolver ir = (TemplateResolver) s_templateResolverCache.get(
|
|
||||||
// name);
|
|
||||||
//
|
|
||||||
// if (ir == null) {
|
|
||||||
// ir = section.getTemplateResolver();
|
|
||||||
// s_templateResolverCache.put(name, ir);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return ir;
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* Fetches the URL of a template for an item. The returned URL is relative
|
|
||||||
* to the webapp context.
|
|
||||||
*/
|
|
||||||
// public String getTemplateURL(ContentSection section,
|
|
||||||
// ContentItem item,
|
|
||||||
// HttpServletRequest request,
|
|
||||||
// RequestContext actx) {
|
|
||||||
//
|
|
||||||
// String templateURL = getTemplateResolver(section).getTemplate(section,
|
|
||||||
// item,
|
|
||||||
// request);
|
|
||||||
//
|
|
||||||
// return templateURL;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.xml.Document;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
*
|
|
||||||
* XMLPage
|
|
||||||
*
|
|
||||||
* Designed to allow you to output straight XML directly from the ContentItem
|
|
||||||
* that implements XMLGenerator, with none of the surrounding headers, footers, etc
|
|
||||||
*
|
|
||||||
* @author slater@arsdigita.com
|
|
||||||
*
|
|
||||||
***/
|
|
||||||
|
|
||||||
public class ItemXML extends ResourceHandlerImpl {
|
|
||||||
|
|
||||||
public ItemXML() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
|
|
||||||
ContentItem item = getContentItem(request);
|
|
||||||
|
|
||||||
Element content = new Element("cms:item", CMS.CMS_XML_NS);
|
|
||||||
|
|
||||||
// ContentItemXMLRenderer renderer =
|
|
||||||
// new ContentItemXMLRenderer(content);
|
|
||||||
//ToDo
|
|
||||||
// renderer.setWrapAttributes(true);
|
|
||||||
// renderer.setWrapRoot(false);
|
|
||||||
// renderer.setWrapObjects(false);
|
|
||||||
//
|
|
||||||
// renderer.walk(item, SimpleXMLGenerator.ADAPTER_CONTEXT);
|
|
||||||
//ToDo End
|
|
||||||
|
|
||||||
Document doc;
|
|
||||||
try {
|
|
||||||
doc = new Document(content);
|
|
||||||
} catch (javax.xml.parsers.ParserConfigurationException e) {
|
|
||||||
throw new javax.servlet.ServletException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputStream out = response.getOutputStream();
|
|
||||||
try {
|
|
||||||
out.write(doc.toString(true).getBytes());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ServletException(e);
|
|
||||||
} finally {
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>A {@link com.arsdigita.cms.dispatcher.CMSPage} used for serving
|
|
||||||
* content items.</p>
|
|
||||||
*
|
|
||||||
* <p>This page contains a <code>ContentPanel</code> component which fetches
|
|
||||||
* the {@link com.arsdigita.cms.dispatcher.XMLGenerator} for the content
|
|
||||||
* section.</p>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class MasterPage extends CMSPage {
|
|
||||||
|
|
||||||
public MasterPage() {
|
|
||||||
super("Master", new SimpleContainer());
|
|
||||||
setIdAttr("master_page");
|
|
||||||
|
|
||||||
add(new ContentPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @return The current content section
|
|
||||||
*/
|
|
||||||
public ContentSection getContentSection(HttpServletRequest request) {
|
|
||||||
// Resets all content sections associations.
|
|
||||||
ContentSection section = super.getContentSection(request);
|
|
||||||
Assert.exists(section);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>This class contains methods for registering and resolving {@link
|
|
||||||
* ResourceHandler CMS resources} in a specific content section.</p>
|
|
||||||
*
|
|
||||||
* <p>The <tt>PageResolver</tt> includes methods for caching resource
|
|
||||||
* mappings.</p>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public abstract class PageResolver {
|
|
||||||
|
|
||||||
private BigDecimal m_sectionID;
|
|
||||||
|
|
||||||
// Used for caching pages
|
|
||||||
private HashMap m_pages;
|
|
||||||
|
|
||||||
|
|
||||||
public PageResolver() {
|
|
||||||
m_pages = new HashMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContentSectionID(BigDecimal id) {
|
|
||||||
m_sectionID = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BigDecimal getContentSectionID() {
|
|
||||||
return m_sectionID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the page associated with the request URL.
|
|
||||||
*
|
|
||||||
* @param url The content section-relative URL stub
|
|
||||||
* @return The resource
|
|
||||||
*/
|
|
||||||
public ResourceHandler getPage(String url) {
|
|
||||||
return (ResourceHandler) m_pages.get(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a page to the content section.
|
|
||||||
*
|
|
||||||
* @param page The master page
|
|
||||||
* @param url The desired URL of the page
|
|
||||||
*/
|
|
||||||
public abstract void registerPage(ResourceHandler page, String url);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a page to the content section.
|
|
||||||
*
|
|
||||||
* @param page The master page
|
|
||||||
* @param url The desired URL of the page
|
|
||||||
*/
|
|
||||||
public abstract void unregisterPage(ResourceHandler page, String url);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a page into the page resolver cache.
|
|
||||||
*
|
|
||||||
* @param url The URL of the resource to load into the cache
|
|
||||||
* @param page The resource
|
|
||||||
*/
|
|
||||||
public void loadPage(String url, ResourceHandler page) {
|
|
||||||
m_pages.put(url, page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes a page from the page resolver cache.
|
|
||||||
*
|
|
||||||
* @param url The URL of the resource to remove from the cache
|
|
||||||
*/
|
|
||||||
public void releasePage(String url) {
|
|
||||||
m_pages.remove(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.Dispatcher;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for resources that can be served.
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id$
|
|
||||||
**/
|
|
||||||
public interface ResourceHandler extends Dispatcher {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by the {@link com.arsdigita.dispatcher.Dispatcher}
|
|
||||||
* that initializes this page.
|
|
||||||
*/
|
|
||||||
public void init() throws ServletException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content section context for this resource.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @return A content section or null if there is none
|
|
||||||
* @pre ( request != null )
|
|
||||||
*/
|
|
||||||
public ContentSection getContentSection(HttpServletRequest request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the content item context for this resource.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
* @return A content item or null if there is none
|
|
||||||
* @pre ( request != null )
|
|
||||||
*/
|
|
||||||
public ContentItem getContentItem(HttpServletRequest request);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.dispatcher.RequestContext;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.apache.shiro.authz.AuthorizationException;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for resources that can be served.
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id$
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class ResourceHandlerImpl implements ResourceHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by the {@link com.arsdigita.dispatcher.Dispatcher}
|
|
||||||
* that initializes this page.
|
|
||||||
*/
|
|
||||||
public void init() throws ServletException {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content section
|
|
||||||
*/
|
|
||||||
public ContentSection getContentSection(HttpServletRequest request) {
|
|
||||||
// resets all content sections associations
|
|
||||||
ContentSection section = CMSDispatcher.getContentSection(request);
|
|
||||||
Assert.exists(section);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content item.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content item
|
|
||||||
*/
|
|
||||||
public ContentItem getContentItem(HttpServletRequest request) {
|
|
||||||
// resets all content item associations
|
|
||||||
return CMSDispatcher.getContentItem(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkUserAccess(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx,
|
|
||||||
ContentItem item) {
|
|
||||||
if (!CdiUtil.createCdiUtil().findBean(PermissionChecker.class)
|
|
||||||
.isPermitted(ItemPrivileges.VIEW_PUBLISHED, item)) {
|
|
||||||
throw new AuthorizationException(
|
|
||||||
"cms.dispatcher.no_permission_to_access_resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Services this resource.
|
|
||||||
*
|
|
||||||
* @param request The servlet request object
|
|
||||||
* @param response the servlet response object
|
|
||||||
* @param actx The request context
|
|
||||||
*/
|
|
||||||
public abstract void dispatch(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
RequestContext actx)
|
|
||||||
throws IOException, ServletException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,445 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.CMSConfig;
|
|
||||||
import com.arsdigita.cms.ContentItem;
|
|
||||||
import com.arsdigita.cms.ContentItemXMLRenderer;
|
|
||||||
import com.arsdigita.cms.ExtraXMLGenerator;
|
|
||||||
import com.arsdigita.cms.SecurityManager;
|
|
||||||
import com.arsdigita.cms.UserDefinedContentItem;
|
|
||||||
import com.arsdigita.cms.XMLDeliveryCache;
|
|
||||||
import com.arsdigita.cms.util.GlobalizationUtil;
|
|
||||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
|
||||||
import com.arsdigita.domain.DomainObjectFactory;
|
|
||||||
import com.arsdigita.domain.DomainObjectTraversal;
|
|
||||||
import com.arsdigita.domain.SimpleDomainObjectTraversalAdapter;
|
|
||||||
import com.arsdigita.kernel.Kernel;
|
|
||||||
import com.arsdigita.kernel.Party;
|
|
||||||
import com.arsdigita.kernel.permissions.PermissionDescriptor;
|
|
||||||
import com.arsdigita.kernel.permissions.PermissionService;
|
|
||||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
|
||||||
import com.arsdigita.metadata.DynamicObjectType;
|
|
||||||
import com.arsdigita.persistence.OID;
|
|
||||||
import com.arsdigita.persistence.metadata.Property;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>The default <tt>XMLGenerator</tt> implementation.</p>
|
|
||||||
*
|
|
||||||
* @author Michael Pih
|
|
||||||
* @version $Revision: #20 $ $DateTime: 2004/08/17 23:15:09 $
|
|
||||||
* @version $Id: SimpleXMLGenerator.java 2167 2011-06-19 21:12:12Z pboy $
|
|
||||||
*/
|
|
||||||
public class SimpleXMLGenerator implements XMLGenerator {
|
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger(SimpleXMLGenerator.class);
|
|
||||||
public static final String ADAPTER_CONTEXT = SimpleXMLGenerator.class.getName();
|
|
||||||
/**
|
|
||||||
* jensp 2011-10-23: Sometimes the extra XML is not needed, for example
|
|
||||||
* when embedding the XML of a content item into the XML output of another
|
|
||||||
* content item. The default value {@code true}. To change the value
|
|
||||||
* call {@link #setUseExtraXml(booelan)} after creating an instance of
|
|
||||||
* your generator.
|
|
||||||
*/
|
|
||||||
private boolean useExtraXml = true;
|
|
||||||
/**
|
|
||||||
* jensp 2012-04-18: This value is forwarded to this ExtraXMLGenerators
|
|
||||||
* by calling {@link ExtraXMLGenerator#setListMode(boolean)}. The behavior
|
|
||||||
* triggered by this value depends on the specific implementation of
|
|
||||||
* the {@code ExtraXMLGenerator}
|
|
||||||
*/
|
|
||||||
private boolean listMode = false;
|
|
||||||
/**
|
|
||||||
* Extra attributes for the cms:item element.
|
|
||||||
*/
|
|
||||||
private final Map<String, String> itemAttributes = new LinkedHashMap<String, String>();
|
|
||||||
/**
|
|
||||||
* Allows to overwrite the name and the namespace of the XML element
|
|
||||||
* used to wrap the rendered item.
|
|
||||||
*/
|
|
||||||
private String itemElemName = "cms:item";
|
|
||||||
private String itemElemNs = CMS.CMS_XML_NS;
|
|
||||||
|
|
||||||
// Register general purpose adaptor for all content items
|
|
||||||
static {
|
|
||||||
s_log.debug("Static initializer starting...");
|
|
||||||
final SimpleDomainObjectTraversalAdapter adapter = new SimpleDomainObjectTraversalAdapter();
|
|
||||||
adapter.addAssociationProperty("/object/type");
|
|
||||||
adapter.addAssociationProperty("/object/categories");
|
|
||||||
|
|
||||||
DomainObjectTraversal.registerAdapter(
|
|
||||||
ContentItem.BASE_DATA_OBJECT_TYPE,
|
|
||||||
adapter,
|
|
||||||
ADAPTER_CONTEXT);
|
|
||||||
s_log.debug("Static initializer finished");
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleXMLGenerator() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUseExtraXml(final boolean useExtraXml) {
|
|
||||||
this.useExtraXml = useExtraXml;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setListMode(final boolean listMode) {
|
|
||||||
this.listMode = listMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addItemAttribute(final String name, final String value) {
|
|
||||||
itemAttributes.put(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setItemElemName(final String itemElemName, final String itemElemNs) {
|
|
||||||
this.itemElemName = itemElemName;
|
|
||||||
this.itemElemNs = itemElemNs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the XML to render the content panel.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param parent The parent DOM element
|
|
||||||
* @param useContext The use context
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateXML(final PageState state, final Element parent, final String useContext) {
|
|
||||||
//final long start = System.nanoTime();
|
|
||||||
|
|
||||||
//ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
ContentItem item = getContentItem(state);
|
|
||||||
|
|
||||||
s_log.info("Generate XML for item " + item.getOID());
|
|
||||||
|
|
||||||
Party currentParty = Kernel.getContext().getParty();
|
|
||||||
if (currentParty == null) {
|
|
||||||
currentParty = Kernel.getPublicUser();
|
|
||||||
}
|
|
||||||
// check if current user can edit the current item (nb privilege is granted on draft item, but live item
|
|
||||||
// has draft as its permission context
|
|
||||||
//
|
|
||||||
// Note that the xml that is generated is only of use if you DO NOT CACHE content pages.
|
|
||||||
// cg.
|
|
||||||
final PermissionDescriptor edit = new PermissionDescriptor(
|
|
||||||
PrivilegeDescriptor.get(SecurityManager.CMS_EDIT_ITEM), item, currentParty);
|
|
||||||
if (PermissionService.checkPermission(edit)) {
|
|
||||||
parent.addAttribute("canEdit", "true");
|
|
||||||
final Element canEditElem = parent.newChildElement("canEdit");
|
|
||||||
canEditElem.setText("true");
|
|
||||||
|
|
||||||
}
|
|
||||||
final PermissionDescriptor publish = new PermissionDescriptor(
|
|
||||||
PrivilegeDescriptor.get(SecurityManager.CMS_PUBLISH), item, currentParty);
|
|
||||||
if (PermissionService.checkPermission(publish)) {
|
|
||||||
parent.addAttribute("canPublish", "true");
|
|
||||||
}
|
|
||||||
final String className = item.getDefaultDomainClass();
|
|
||||||
|
|
||||||
// Ensure correct subtype of ContentItem is instantiated
|
|
||||||
if (!item.getClass().getName().equals(className)) {
|
|
||||||
s_log.info("Specializing item");
|
|
||||||
try {
|
|
||||||
item = (ContentItem) DomainObjectFactory.newInstance(
|
|
||||||
new OID(item.getObjectType().getQualifiedName(), item.getID()));
|
|
||||||
} catch (DataObjectNotFoundException ex) {
|
|
||||||
throw new UncheckedWrapperException(
|
|
||||||
(String) GlobalizationUtil.globalize(
|
|
||||||
"cms.dispatcher.cannot_find_domain_object").localize(),
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementing XMLGenerator directly is now deprecated
|
|
||||||
if (item instanceof XMLGenerator) {
|
|
||||||
s_log.info("Item implements XMLGenerator interface");
|
|
||||||
final XMLGenerator xitem = (XMLGenerator) item;
|
|
||||||
xitem.generateXML(state, parent, useContext);
|
|
||||||
|
|
||||||
} else if ("com.arsdigita.cms.UserDefinedContentItem".equals(className)) {
|
|
||||||
s_log.info("Item is a user defined content item");
|
|
||||||
final UserDefinedContentItem UDItem = (UserDefinedContentItem) item;
|
|
||||||
generateUDItemXML(UDItem, state, parent, useContext);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
s_log.info("Item is using DomainObjectXMLRenderer");
|
|
||||||
|
|
||||||
// This is the preferred method
|
|
||||||
//final Element content = startElement(useContext, parent);
|
|
||||||
final Element content = startElement(useContext);
|
|
||||||
s_log.debug("Item is not in cache, generating item.");
|
|
||||||
|
|
||||||
final XMLDeliveryCache xmlCache = XMLDeliveryCache.getInstance();
|
|
||||||
|
|
||||||
if (CMSConfig.getInstanceOf().getEnableXmlCache() && xmlCache.isCached(item.getOID(), useContext, listMode)) {
|
|
||||||
xmlCache.retrieveFromCache(content, item.getOID(), useContext, listMode);
|
|
||||||
} else {
|
|
||||||
final ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(content);
|
|
||||||
|
|
||||||
renderer.setWrapAttributes(true);
|
|
||||||
renderer.setWrapRoot(false);
|
|
||||||
renderer.setWrapObjects(false);
|
|
||||||
renderer.setRevisitFullObject(true);
|
|
||||||
|
|
||||||
//System.out.printf("Prepared renderer in %d ms\n", (System.nanoTime() - start)
|
|
||||||
// / 1000000);
|
|
||||||
|
|
||||||
renderer.walk(item, ADAPTER_CONTEXT);
|
|
||||||
|
|
||||||
//System.out.printf("Rendered standard item xml in %d ms\n", (System.nanoTime() - start)
|
|
||||||
// / 1000000);
|
|
||||||
|
|
||||||
//parent.addContent(content);
|
|
||||||
|
|
||||||
//Only item XML Cache End
|
|
||||||
|
|
||||||
// s_log.debug("Content elem content: ");
|
|
||||||
// logElementTree(content);
|
|
||||||
// s_log.debug("Content elem content end -- ");
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 2011-08-27 jensp: Introduced to remove the annoying special templates
|
|
||||||
* for MultiPartArticle, SiteProxy and others. The method called
|
|
||||||
* here was already definied but not used.
|
|
||||||
*
|
|
||||||
* 2011-10-23 jensp: It is now possible to disable the use of
|
|
||||||
* extra XML.
|
|
||||||
*/
|
|
||||||
//final long extraXMLStart = System.nanoTime();
|
|
||||||
if (useExtraXml) {
|
|
||||||
for (ExtraXMLGenerator generator : item.getExtraXMLGenerators()) {
|
|
||||||
generator.setListMode(listMode);
|
|
||||||
generator.generateXML(item, content, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only published items
|
|
||||||
//Only the XML of the item itself, no extra XML
|
|
||||||
if (CMSConfig.getInstanceOf().getEnableXmlCache() && item.isLiveVersion()) {
|
|
||||||
xmlCache.cache(item.getOID(), item, content, useContext, listMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PermissionService.checkPermission(edit)) {
|
|
||||||
final ItemResolver resolver = item.getContentSection().getItemResolver();
|
|
||||||
final Element editLinkElem = content.newChildElement("editLink");
|
|
||||||
final ContentItem draftItem = item.getDraftVersion();
|
|
||||||
editLinkElem.setText(resolver.generateItemURL(state,
|
|
||||||
draftItem,
|
|
||||||
item.getContentSection(),
|
|
||||||
draftItem.getVersion()));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.addContent(content);
|
|
||||||
|
|
||||||
//System.out.printf("Rendered item in %d ms\n\n", (System.nanoTime() - start) / 1000000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the current content item. This method can be overridden to
|
|
||||||
* fetch any {@link com.arsdigita.cms.ContentItem}, but by default,
|
|
||||||
* it fetches the <code>ContentItem</code> that is set in the page state
|
|
||||||
* by the dispatcher.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @return A content item
|
|
||||||
*/
|
|
||||||
protected ContentItem getContentItem(final PageState state) {
|
|
||||||
if (CMS.getContext().hasContentItem()) {
|
|
||||||
return CMS.getContext().getContentItem();
|
|
||||||
} else {
|
|
||||||
final CMSPage page = (CMSPage) state.getPage();
|
|
||||||
return page.getContentItem(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void generateUDItemXML(final UserDefinedContentItem UDItem,
|
|
||||||
final PageState state,
|
|
||||||
final Element parent,
|
|
||||||
final String useContext) {
|
|
||||||
|
|
||||||
final Element element = startElement(useContext, parent);
|
|
||||||
final Element additionalAttrs = UDItemElement(useContext);
|
|
||||||
|
|
||||||
element.addAttribute("type", UDItem.getContentType().getName());
|
|
||||||
element.addAttribute("id", UDItem.getID().toString());
|
|
||||||
element.addAttribute("name", UDItem.getName());
|
|
||||||
element.addAttribute("title", UDItem.getTitle());
|
|
||||||
element.addAttribute("javaClass", UDItem.getContentType().getClassName());
|
|
||||||
|
|
||||||
final DynamicObjectType dot = new DynamicObjectType(UDItem.getSpecificObjectType());
|
|
||||||
final Iterator declaredProperties =
|
|
||||||
dot.getObjectType().getDeclaredProperties();
|
|
||||||
Property currentProperty;
|
|
||||||
Object value;
|
|
||||||
while (declaredProperties.hasNext()) {
|
|
||||||
currentProperty = (Property) declaredProperties.next();
|
|
||||||
value = (Object) UDItem.get(currentProperty.getName());
|
|
||||||
if (value != null) {
|
|
||||||
element.addContent(
|
|
||||||
UDItemAttrElement(currentProperty.getName(),
|
|
||||||
value.toString()));
|
|
||||||
} else {
|
|
||||||
element.addContent(
|
|
||||||
UDItemAttrElement(currentProperty.getName(),
|
|
||||||
"none specified"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//element.addContent(additionalAttrs);
|
|
||||||
//parent.addContent(element);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element startElement(final String useContext, final Element parent) {
|
|
||||||
//Element element = new Element("cms:item", CMS.CMS_XML_NS);
|
|
||||||
//final Element element = new Element(itemElemName, itemElemNs);
|
|
||||||
final Element element = parent.newChildElement(itemElemName, itemElemNs);
|
|
||||||
if (useContext != null) {
|
|
||||||
element.addAttribute("useContext", useContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> attr : itemAttributes.entrySet()) {
|
|
||||||
element.addAttribute(attr.getKey(), attr.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element startElement(final String useContext) {
|
|
||||||
final Element element = new Element(itemElemName, itemElemNs);
|
|
||||||
|
|
||||||
if (useContext != null) {
|
|
||||||
element.addAttribute("useContext", useContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> attr : itemAttributes.entrySet()) {
|
|
||||||
element.addAttribute(attr.getKey(), attr.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element startCachedElement(final String useContext) {
|
|
||||||
final Element element = new Element(itemElemName, itemElemNs) {
|
|
||||||
@Override
|
|
||||||
public Element newChildElement(Element copyFrom) {
|
|
||||||
s_log.debug("Copy of element added to cached elem.");
|
|
||||||
return super.newChildElement(copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Element newChildElement(String name, Element copyFrom) {
|
|
||||||
s_log.debug("Copy of element added to cached elem.");
|
|
||||||
return super.newChildElement(name, copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Element addContent(final Element newContent) {
|
|
||||||
s_log.debug("Content added to cached element");
|
|
||||||
return super.addContent(newContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
if (useContext != null) {
|
|
||||||
element.addAttribute("useContext", useContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> attr : itemAttributes.entrySet()) {
|
|
||||||
element.addAttribute(attr.getKey(), attr.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyElement(final Element parent, final Element element) {
|
|
||||||
final Element copy = parent.newChildElement(element.getName());
|
|
||||||
final Iterator attrs = element.getAttributes().entrySet().iterator();
|
|
||||||
Map.Entry attr;
|
|
||||||
while (attrs.hasNext()) {
|
|
||||||
attr = (Map.Entry) attrs.next();
|
|
||||||
copy.addAttribute((String) attr.getKey(), (String) attr.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
final Iterator childs = element.getChildren().iterator();
|
|
||||||
while (childs.hasNext()) {
|
|
||||||
copyElement(copy, (Element) childs.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.getText() != null) {
|
|
||||||
copy.setText(element.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.getCDATASection() != null) {
|
|
||||||
copy.setCDATASection(element.getCDATASection());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element UDItemElement(final String useContext) {
|
|
||||||
final Element element = new Element("cms:UDItemAttributes", CMS.CMS_XML_NS);
|
|
||||||
/*
|
|
||||||
if ( useContext != null ) {
|
|
||||||
element.addAttribute("useContext", useContext);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element UDItemAttrElement(final String name, final String value) {
|
|
||||||
final Element element = new Element("cms:UDItemAttribute", CMS.CMS_XML_NS);
|
|
||||||
element.addAttribute("UDItemAttrName", name);
|
|
||||||
element.addAttribute("UDItemAttrValue", value);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logElementTree(final Element element) {
|
|
||||||
s_log.debug("Tree of element" + element.getName() + ":\n");
|
|
||||||
s_log.debug("\n" + logElementTree(element, new StringBuilder(), 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String logElementTree(final Element element, final StringBuilder builder, final int depth) {
|
|
||||||
for (int i = 0; i < depth; i++) {
|
|
||||||
builder.append('\t');
|
|
||||||
}
|
|
||||||
builder.append('<').append(element.getName()).append(">\n");
|
|
||||||
|
|
||||||
for (Object childObj : element.getChildren()) {
|
|
||||||
final Element child = (Element) childObj;
|
|
||||||
logElementTree(child, builder, depth + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < depth; i++) {
|
|
||||||
builder.append('\t');
|
|
||||||
}
|
|
||||||
builder.append("</").append(element.getName()).append(">\n");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reimplementation, based on ItemTemplateResolver
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Many sites offer alternative views of the same content item depending on
|
|
||||||
* device or browser, or on user preference. For example, a site may have
|
|
||||||
* "plain" and "fancy" versions of its pages. The fancy versions would be the
|
|
||||||
* defaults, while the plain versions would be appropriate for users with
|
|
||||||
* low-bandwidth connections, older browsers, or a distaste for flashy
|
|
||||||
* appurtenances. In this the case the selection might be made based on a
|
|
||||||
* cookie.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Another common example is the "printable" version of a page. In this case a
|
|
||||||
* query variable might be more appropriate.</p>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Karl Goldstein (karlg@arsdigita.com)
|
|
||||||
* @version $Id: TemplateResolver.java 1967 2009-08-29 21:05:51Z pboy $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface TemplateResolver {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JSP template filename relative to the webapp root.
|
|
||||||
*
|
|
||||||
* @param section The ContentSection for the request
|
|
||||||
* @param item The ContentItem for the request
|
|
||||||
* @param request The current HttpServletRequest
|
|
||||||
*
|
|
||||||
* @return The path to the jsp template.
|
|
||||||
*/
|
|
||||||
public String getTemplate(ContentSection section,
|
|
||||||
ContentItem item,
|
|
||||||
HttpServletRequest request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JSP template filename relative to the webapp root for a given
|
|
||||||
* Template reference.
|
|
||||||
*
|
|
||||||
* @param template The Template to resolve the URL for.
|
|
||||||
*
|
|
||||||
* @return The path to the jsp template.
|
|
||||||
*/
|
|
||||||
public String getTemplatePath(Template template);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the XSL template filename relative to the webapp root for a given
|
|
||||||
* Template reference.
|
|
||||||
*
|
|
||||||
* @param template The Template to resolve the URL for.
|
|
||||||
*
|
|
||||||
* @return The path to the xsl template.
|
|
||||||
*/
|
|
||||||
public String getTemplateXSLPath(Template template);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the TemplateContext parameter in the request
|
|
||||||
*
|
|
||||||
* @param sTemplateContext the template context to set
|
|
||||||
* @param request the request in which to set the template context
|
|
||||||
*/
|
|
||||||
public void setTemplateContext(String sTemplateContext,
|
|
||||||
HttpServletRequest request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the template context from the request.
|
|
||||||
*
|
|
||||||
* @param request the request from which to get the template context
|
|
||||||
*
|
|
||||||
* @return the template context
|
|
||||||
*/
|
|
||||||
public String getTemplateContext(HttpServletRequest request);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.BinaryAsset;
|
|
||||||
import org.librecms.assets.Image;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* This class provides many utility functions for the Content Management
|
|
||||||
* System.</p>
|
|
||||||
* Specifically used by various JSP templates.
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
*/
|
|
||||||
public class Utilities {
|
|
||||||
|
|
||||||
public static final Logger LOGGER = LogManager.getLogger(Utilities.class);
|
|
||||||
|
|
||||||
// Used for caching util lookups
|
|
||||||
private static HashMap m_cache = new HashMap();
|
|
||||||
|
|
||||||
private static Date s_lastSectionRefresh = null;
|
|
||||||
private static Map s_sectionRefreshTimes = Collections.synchronizedMap(
|
|
||||||
new HashMap());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the location of the CMS ContentCenter package.
|
|
||||||
*
|
|
||||||
* @return The URL of the CMS ContentCenter package
|
|
||||||
*
|
|
||||||
* @deprecated use ContentCenter.getURL() instead
|
|
||||||
*/
|
|
||||||
public static String getWorkspaceURL() {
|
|
||||||
|
|
||||||
return CmsConstants.CONTENT_CENTER_URL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the location (URL) of the CMS Services package. Caches the result.
|
|
||||||
*
|
|
||||||
* @return The URL of the CMS Services package
|
|
||||||
*
|
|
||||||
* @deprecated Use Service.getURL( instead
|
|
||||||
*/
|
|
||||||
public static String getServiceURL() {
|
|
||||||
String url = (String) m_cache.get(CmsConstants.SERVICE_PACKAGE_KEY);
|
|
||||||
if (url == null) {
|
|
||||||
// chris.gilbert@westsussex.gov.uk
|
|
||||||
// We don't want application context in this url, especially when
|
|
||||||
// it gets cached in a static variable - if I have a
|
|
||||||
// file that is maintained by a non cms application eg
|
|
||||||
// forum, then I can end up with a url that doesn't work
|
|
||||||
// and so breaks file links everywhere
|
|
||||||
// url = getSingletonPackageURLSansContext(CMS.SERVICE_PACKAGE_KEY);
|
|
||||||
url = CmsConstants.SERVICE_URL;
|
|
||||||
m_cache.put(CmsConstants.SERVICE_PACKAGE_KEY, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL to log out.
|
|
||||||
*
|
|
||||||
* @return The logout URL
|
|
||||||
*/
|
|
||||||
public static String getLogoutURL() {
|
|
||||||
//StringBuffer buf = new StringBuffer(getServiceURL());
|
|
||||||
StringBuilder buf = new StringBuilder(CmsConstants.SERVICE_URL);
|
|
||||||
buf.append("logout");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URL which serves a binary asset.
|
|
||||||
*
|
|
||||||
* @param asset The binary asset
|
|
||||||
*
|
|
||||||
* @return the URL which will serve the specified binary asset
|
|
||||||
*
|
|
||||||
* @deprecated Use Service.getAssetURL(BinaryAsset asset) instead
|
|
||||||
*/
|
|
||||||
public static String getAssetURL(BinaryAsset asset) {
|
|
||||||
return getAssetURL(asset.getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constuct a URL which serves a binary asset.
|
|
||||||
*
|
|
||||||
* @param assetId The asset ID
|
|
||||||
*
|
|
||||||
* @return the URL which will serve the specified binary asset
|
|
||||||
*
|
|
||||||
* @deprecated Use Service.getAssetURL(BigDecimal assetId) instead
|
|
||||||
*/
|
|
||||||
public static String getAssetURL(long assetId) {
|
|
||||||
// StringBuffer buf = new StringBuffer(getServiceURL());
|
|
||||||
StringBuilder buf = new StringBuilder(CmsConstants.SERVICE_URL);
|
|
||||||
buf.append("stream/asset?");
|
|
||||||
buf.append(CmsConstants.ASSET_ID).append("=").append(assetId);
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URL which serves an image.
|
|
||||||
*
|
|
||||||
* @param asset The image asset whose image is to be served
|
|
||||||
*
|
|
||||||
* @return the URL which will serve the specified image asset
|
|
||||||
*
|
|
||||||
* @deprecated Use Service.getImageURL(ImageAsset) instead!
|
|
||||||
*/
|
|
||||||
public static String getImageURL(Image asset) {
|
|
||||||
// StringBuffer buf = new StringBuffer(getServiceURL());
|
|
||||||
StringBuilder buf = new StringBuilder(CmsConstants.SERVICE_URL);
|
|
||||||
buf.append("stream/image/?");
|
|
||||||
buf.append(CmsConstants.IMAGE_ID).append("=")
|
|
||||||
.append(asset.getObjectId());
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getGlobalAssetsURL() {
|
|
||||||
return getWebappContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the context path of the request. This is typically "/".
|
|
||||||
*
|
|
||||||
* @return The webapp context path
|
|
||||||
*/
|
|
||||||
public static String getWebappContext() {
|
|
||||||
return DispatcherHelper.getWebappContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for the last refresh on authoring kits or content types in a
|
|
||||||
* section.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static synchronized Date
|
|
||||||
getLastSectionRefresh(ContentSection section) {
|
|
||||||
|
|
||||||
// cache by URL string instead of by section object to avoid
|
|
||||||
// holding the reference.
|
|
||||||
String sectionURL = section.getPrimaryUrl();
|
|
||||||
|
|
||||||
Date lastModified = (Date) s_sectionRefreshTimes.get(sectionURL);
|
|
||||||
if (lastModified == null) {
|
|
||||||
lastModified = new Date();
|
|
||||||
s_lastSectionRefresh = lastModified;
|
|
||||||
s_sectionRefreshTimes.put(sectionURL, lastModified);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lastModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for the last refresh on authoring kits or content types in any
|
|
||||||
* section.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static Date getLastSectionRefresh() {
|
|
||||||
|
|
||||||
// instantiate last refresh lazily to ensure that first result is
|
|
||||||
// predictable.
|
|
||||||
if (s_lastSectionRefresh == null) {
|
|
||||||
s_lastSectionRefresh = new Date();
|
|
||||||
}
|
|
||||||
return s_lastSectionRefresh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force the authoring UI to reload. This should be done every time an
|
|
||||||
* authoring kit or a content type are updated.
|
|
||||||
*/
|
|
||||||
public static void refreshItemUI(PageState state) {
|
|
||||||
// Drop the authoring kit UI to force it to refresh
|
|
||||||
// THE URL SHOULD NOT BE HARDCODED !
|
|
||||||
|
|
||||||
ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
|
|
||||||
// OLD APPROACH: used in conjunction with CMSDispatcher. This
|
|
||||||
// shouldn't do any harm even if CMSDispatcher is not being used.
|
|
||||||
CMSDispatcher.releaseResource(section, "admin/item");
|
|
||||||
refreshAdminUI(state);
|
|
||||||
|
|
||||||
// NEW APPROACH: used in conjunction with
|
|
||||||
// ContentSectionDispatcher. cache by URL string instead of by
|
|
||||||
// section object to avoid holding the reference. This shouldn't
|
|
||||||
// do any harm even if ContentSectionDispatcher is not being used.
|
|
||||||
s_lastSectionRefresh = new Date();
|
|
||||||
s_sectionRefreshTimes.put(section.getPrimaryUrl(),
|
|
||||||
s_lastSectionRefresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force the authoring UI to reload. This should be done every time an
|
|
||||||
* authoring kit or a content type are updated.
|
|
||||||
*/
|
|
||||||
public static void refreshAdminUI(PageState state) {
|
|
||||||
// Drop the admin UI to force it to refresh
|
|
||||||
// THE URL SHOULD NOT BE HARDCODED !
|
|
||||||
|
|
||||||
ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
|
|
||||||
CMSDispatcher.releaseResource(section, "admin");
|
|
||||||
CMSDispatcher.releaseResource(section, "admin/index");
|
|
||||||
CMSDispatcher.releaseResource(section, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the "pragma: no-cache" header to the HTTP response to make sure the
|
|
||||||
* browser does not cache tha page
|
|
||||||
*
|
|
||||||
* @param response The HTTP response
|
|
||||||
*
|
|
||||||
* @deprecated use
|
|
||||||
* com.arsdigita.dispatcher.DispatcherHelper.cacheDisable(HttpServletResponse)
|
|
||||||
*/
|
|
||||||
public static void disableBrowserCache(HttpServletResponse response) {
|
|
||||||
response.addHeader("pragma", "no-cache");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.dispatcher;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Generates XML representing a Content Item.</p>
|
|
||||||
*
|
|
||||||
* <p>As the last step of servicing a page, the
|
|
||||||
* {@link com.arsdigita.cms.dispatcher.MasterPage} will go through the
|
|
||||||
* hierarchy of its components and ask each of them to convert themselves
|
|
||||||
* to XML. A MasterPage contains a special component that knows how to ask
|
|
||||||
* its content section for the XML generator that should be applied. The
|
|
||||||
* XML generator's <code>generateXML</code> method in turn asks the
|
|
||||||
* containing page for the content item, the one that the
|
|
||||||
* {@link com.arsdigita.cms.dispatcher.ItemResolver} found before, and
|
|
||||||
* formats it as an XML document.</p>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public interface XMLGenerator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the XML to render the content panel.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param parent The parent DOM element
|
|
||||||
* @param useContext The use context
|
|
||||||
*/
|
|
||||||
public void generateXML(PageState state, Element parent, String useContext);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.lifecycle;
|
|
||||||
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for lifecycle durations.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:pihman@arsdigita.com">Michael Pih</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com>Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class Duration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience wrapper around {@link #formatDuration(long)}.
|
|
||||||
*
|
|
||||||
* @param minutes
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @see #formatDuration(long)
|
|
||||||
* @pre minutes != null
|
|
||||||
*/
|
|
||||||
public static String formatDuration(final Long minutes) {
|
|
||||||
Assert.exists(minutes, "minutes");
|
|
||||||
return formatDuration(minutes.longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a duration longo a user friendly format of the form "x days, h
|
|
||||||
* hours, m minutes".
|
|
||||||
*
|
|
||||||
* @param minutes the duration in minutes
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String formatDuration(final long minutes) {
|
|
||||||
long[] dhm = formatDHM(minutes);
|
|
||||||
final StringBuilder buffer = new StringBuilder();
|
|
||||||
|
|
||||||
if (dhm[0] > 0) {
|
|
||||||
buffer.append(dhm[0]).append(" days");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dhm[1] > 0) {
|
|
||||||
if (dhm[0] > 0) {
|
|
||||||
buffer.append(", ");
|
|
||||||
}
|
|
||||||
buffer.append(dhm[1]).append(" hours");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dhm[0] > 0 || dhm[1] > 0) {
|
|
||||||
buffer.append(", ");
|
|
||||||
}
|
|
||||||
buffer.append(dhm[2]).append(" minutes");
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats time in minutes longo a days/hours/minutes format.
|
|
||||||
*
|
|
||||||
* @param minutes
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long[] formatDHM(final long minutes) {
|
|
||||||
long[] dhm = new long[3];
|
|
||||||
|
|
||||||
long days = minutes / (60 * 24);
|
|
||||||
long hours = minutes / 60; // no pun longended
|
|
||||||
long mins = minutes;
|
|
||||||
|
|
||||||
if (days > 0) {
|
|
||||||
hours -= (days * 24);
|
|
||||||
mins -= (days * 24 * 60);
|
|
||||||
}
|
|
||||||
if (hours > 0) {
|
|
||||||
mins -= (hours * 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
dhm[0] = days;
|
|
||||||
dhm[1] = hours;
|
|
||||||
dhm[2] = mins;
|
|
||||||
return dhm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats time in minutes longo a days/hours/minutes format.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @see #formatDHM(long)
|
|
||||||
* @param minutes timespan in minutes
|
|
||||||
*/
|
|
||||||
public static Long[] formatDHM(final Long minutes) {
|
|
||||||
long dhm[] = formatDHM(minutes.longValue());
|
|
||||||
return copyArray(dhm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Long[] copyArray(long[] from) {
|
|
||||||
Assert.exists(from, "from");
|
|
||||||
Long[] to = new Long[from.length];
|
|
||||||
for (int ii = 0; ii < from.length; ii++) {
|
|
||||||
to[ii] = from[ii];
|
|
||||||
}
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.list.ListModelBuilder;
|
|
||||||
import com.arsdigita.bebop.tree.TreeModelBuilder;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.SelectionPanel;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base component for use in CMS admin panes.
|
|
||||||
*
|
|
||||||
* @param <T> Type managed by the {@link SingleSelectionModel} used by instances
|
|
||||||
* of this class.
|
|
||||||
*
|
|
||||||
* @author Justin Ross <jross@redhat.com>
|
|
||||||
*/
|
|
||||||
public abstract class BaseAdminPane<T> extends SelectionPanel<T> {
|
|
||||||
|
|
||||||
protected BaseAdminPane() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final Component title,
|
|
||||||
final Component selector) {
|
|
||||||
super(title, selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final GlobalizedMessage title,
|
|
||||||
final Component selector) {
|
|
||||||
super(title, selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final Component title,
|
|
||||||
final Component selector,
|
|
||||||
final SingleSelectionModel<T> model) {
|
|
||||||
super(title, selector, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final GlobalizedMessage title,
|
|
||||||
final Component selector,
|
|
||||||
final SingleSelectionModel<T> model) {
|
|
||||||
super(title, selector, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final Component title,
|
|
||||||
final ListModelBuilder builder) {
|
|
||||||
super(title, builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final GlobalizedMessage title,
|
|
||||||
final ListModelBuilder builder) {
|
|
||||||
super(title, builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final Component title,
|
|
||||||
final TreeModelBuilder builder) {
|
|
||||||
super(title, builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseAdminPane(final GlobalizedMessage title,
|
|
||||||
final TreeModelBuilder builder) {
|
|
||||||
super(title, builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static GlobalizedMessage gz(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String lz(final String key) {
|
|
||||||
return (String) gz(key).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Justin Ross
|
|
||||||
*/
|
|
||||||
public abstract class BaseDeleteForm extends BaseForm
|
|
||||||
implements FormProcessListener {
|
|
||||||
|
|
||||||
protected final Submit m_delete;
|
|
||||||
protected final Submit m_cancel;
|
|
||||||
|
|
||||||
public BaseDeleteForm(final Component message) {
|
|
||||||
super("delete", new Label(gz("cms.ui.attention")));
|
|
||||||
|
|
||||||
addComponent(message);
|
|
||||||
|
|
||||||
m_delete = new Submit("delete", gz("cms.ui.delete"));
|
|
||||||
addAction(m_delete);
|
|
||||||
|
|
||||||
m_cancel = new Submit("cancel", gz("cms.ui.cancel"));
|
|
||||||
addAction(m_cancel);
|
|
||||||
|
|
||||||
addProcessListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseDeleteForm(final GlobalizedMessage message) {
|
|
||||||
this(new Label(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isCancelled(final PageState state) {
|
|
||||||
return m_cancel.isSelected(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.GridPanel;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.form.FormErrorDisplay;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.TrimmedStringParameter;
|
|
||||||
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.Cancellable;
|
|
||||||
import com.arsdigita.toolbox.ui.Section;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience class for CMS forms.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @author <a href="mailto:jross@redhat.com">Justin Ross</a>
|
|
||||||
*/
|
|
||||||
public abstract class BaseForm extends Form implements Cancellable {
|
|
||||||
|
|
||||||
private final BodySection m_body;
|
|
||||||
private final BoxPanel m_actions;
|
|
||||||
private Cancel m_cancel;
|
|
||||||
|
|
||||||
protected BaseForm(final String name, final Label heading) {
|
|
||||||
super(name, new GridPanel(1));
|
|
||||||
|
|
||||||
setRedirecting(true);
|
|
||||||
|
|
||||||
m_body = new BodySection(heading);
|
|
||||||
m_actions = new BoxPanel(BoxPanel.HORIZONTAL);
|
|
||||||
|
|
||||||
add(m_body);
|
|
||||||
add(m_actions);
|
|
||||||
|
|
||||||
addComponent(new FormErrorDisplay(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BaseForm(final String name,
|
|
||||||
final GlobalizedMessage heading) {
|
|
||||||
this(name, new Label(heading));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BodySection extends Section {
|
|
||||||
|
|
||||||
final SimpleContainer m_container;
|
|
||||||
|
|
||||||
BodySection(final Label heading) {
|
|
||||||
setHeading(heading);
|
|
||||||
|
|
||||||
m_container = new GridPanel(2);
|
|
||||||
setBody(m_container);
|
|
||||||
}
|
|
||||||
|
|
||||||
final void add(final Component component) {
|
|
||||||
m_container.add(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
final void add(final Component component, int hints) {
|
|
||||||
m_container.add(component, hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addComponent(final Component component) {
|
|
||||||
m_body.add(component, GridPanel.FULL_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addField(final Label name, final Component widget) {
|
|
||||||
m_body.add(name);
|
|
||||||
m_body.add(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addField(final GlobalizedMessage name,
|
|
||||||
final Component widget) {
|
|
||||||
addField(new Label(name), widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addAction(final Submit button) {
|
|
||||||
m_actions.add(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addAction(final Cancel button) {
|
|
||||||
m_cancel = button;
|
|
||||||
m_actions.add(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addSecurityListener(final String action) {
|
|
||||||
addSubmissionListener(new FormSecurityListener(action));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void addSecurityListener(final String action,
|
|
||||||
final ContentItemRequestLocal item) {
|
|
||||||
addSubmissionListener(new FormSecurityListener(action, item));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled(final PageState state) {
|
|
||||||
return m_cancel != null && m_cancel.isSelected(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final class Name extends TextField {
|
|
||||||
|
|
||||||
public Name(final String key, final int max, final boolean required) {
|
|
||||||
super(new TrimmedStringParameter(key));
|
|
||||||
|
|
||||||
if (required) {
|
|
||||||
addValidationListener(new NotEmptyValidationListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
setSize(40);
|
|
||||||
setMaxLength(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final class Description extends TextArea {
|
|
||||||
|
|
||||||
public Description(final String key,
|
|
||||||
final int maxLength,
|
|
||||||
final boolean isRequired) {
|
|
||||||
super(new TrimmedStringParameter(key));
|
|
||||||
Assert.isTrue(maxLength > 0, "Max length cannot be negative");
|
|
||||||
|
|
||||||
if (isRequired) {
|
|
||||||
addValidationListener(NotNullValidationListener.DEFAULT);
|
|
||||||
}
|
|
||||||
addValidationListener(new StringLengthValidationListener(maxLength));
|
|
||||||
setCols(40);
|
|
||||||
setRows(5);
|
|
||||||
setWrap(TextArea.SOFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final class Finish extends Submit {
|
|
||||||
|
|
||||||
public Finish() {
|
|
||||||
super("finish", gz("cms.ui.finish"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final class Cancel extends Submit {
|
|
||||||
|
|
||||||
public Cancel() {
|
|
||||||
super("cancel", gz("cms.ui.cancel"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final GlobalizedMessage gz(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static final String lz(final String key) {
|
|
||||||
return (String) gz(key).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.ModalPanel;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:jross@redhat.com">Justin Ross</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public abstract class BaseItemPane extends ModalPanel {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger
|
|
||||||
(BaseItemPane.class);
|
|
||||||
|
|
||||||
protected BaseItemPane() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final static GlobalizedMessage gz(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final static String lz(final String key) {
|
|
||||||
return (String) gz(key).localize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Tree;
|
|
||||||
import com.arsdigita.bebop.event.ChangeEvent;
|
|
||||||
import com.arsdigita.bebop.event.ChangeListener;
|
|
||||||
import com.arsdigita.bebop.event.TreeExpansionEvent;
|
|
||||||
import com.arsdigita.bebop.event.TreeExpansionListener;
|
|
||||||
import com.arsdigita.bebop.tree.TreeModelBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience class for CMS trees.
|
|
||||||
*
|
|
||||||
* @author Justin Ross <jross@redhat.com>
|
|
||||||
*/
|
|
||||||
public class BaseTree extends Tree {
|
|
||||||
|
|
||||||
public BaseTree(final TreeModelBuilder builder) {
|
|
||||||
super(builder);
|
|
||||||
|
|
||||||
addChangeListener(new Change());
|
|
||||||
addTreeExpansionListener(new TreeExpansion());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Change implements ChangeListener {
|
|
||||||
public final void stateChanged(final ChangeEvent e) {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
final Object key = BaseTree.this.getSelectedKey(state);
|
|
||||||
|
|
||||||
if (key != null) {
|
|
||||||
expand(key.toString(), state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TreeExpansion implements TreeExpansionListener {
|
|
||||||
public final void treeExpanded(final TreeExpansionEvent e) {
|
|
||||||
//s_log.error("expanded");
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void treeCollapsed(final TreeExpansionEvent e) {
|
|
||||||
//s_log.error("collapsed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.SegmentedPanel;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Text;
|
|
||||||
import com.arsdigita.bebop.Tree;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.tree.TreeCellRenderer;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderRequestLocal;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderTreeModelBuilder;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderTreeModelController;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.libreccm.categorization.Category;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.core.CcmObject;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
import org.librecms.dispatcher.ItemResolver;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pane that contains a folder tree on the left and a folder manipulator on
|
|
||||||
* the right. It is a part of the content section main page and is displayed as
|
|
||||||
* the "Browse" tab.
|
|
||||||
*
|
|
||||||
* @author David LutterKort <dlutter@redhat.com>
|
|
||||||
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class BrowsePane extends LayoutPanel implements Resettable {
|
|
||||||
|
|
||||||
private final BaseTree tree;
|
|
||||||
private final SingleSelectionModel selectionModel;
|
|
||||||
private final FolderSelectionModel folderModel; // To support legacy UI code
|
|
||||||
private final FolderRequestLocal folderRequestLocal;
|
|
||||||
private final FlatItemList flatItemList;
|
|
||||||
|
|
||||||
public BrowsePane() {
|
|
||||||
|
|
||||||
/* The folder tree displayed on the left side / left column */
|
|
||||||
tree = new BaseTree(new FolderTreeModelBuilder() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Folder getRootFolder(final PageState state) {
|
|
||||||
final ContentSection section = CMS
|
|
||||||
.getContext()
|
|
||||||
.getContentSection();
|
|
||||||
return section.getRootDocumentsFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
selectionModel = tree.getSelectionModel();
|
|
||||||
folderModel = new FolderSelectionModel(selectionModel) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Long getRootFolderID(final PageState state) {
|
|
||||||
final ContentSection section = CMS
|
|
||||||
.getContext()
|
|
||||||
.getContentSection();
|
|
||||||
return section.getRootDocumentsFolder().getObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
folderRequestLocal = new FolderRequestLocal(folderModel);
|
|
||||||
|
|
||||||
final SegmentedPanel left = new SegmentedPanel();
|
|
||||||
setLeft(left);
|
|
||||||
|
|
||||||
final Label heading = new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.folder_browser",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
left.addSegment(heading, tree);
|
|
||||||
|
|
||||||
flatItemList = new FlatItemList(folderRequestLocal, folderModel);
|
|
||||||
setBody(flatItemList);
|
|
||||||
|
|
||||||
flatItemList.getManipulator().getItemView().addProcessListener(
|
|
||||||
new ProcessListener());
|
|
||||||
flatItemList.getManipulator().getTargetSelector().addProcessListener(
|
|
||||||
new ProcessListener());
|
|
||||||
flatItemList.getManipulator().getTargetSelector().addSubmissionListener(
|
|
||||||
new SubmissionListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.addActionListener(new FolderListener());
|
|
||||||
page.addActionListener(new TreeListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void reset(final PageState state) {
|
|
||||||
super.reset(state);
|
|
||||||
|
|
||||||
flatItemList.reset(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private classes and methods
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private final class ProcessListener implements FormProcessListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void process(final FormSectionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (event.getSource() == flatItemList.getManipulator().getItemView()) {
|
|
||||||
// Hide everything except for the flat item list
|
|
||||||
tree.setVisible(state, false);
|
|
||||||
} else if (event.getSource() == flatItemList.getManipulator()
|
|
||||||
.getTargetSelector()) {
|
|
||||||
tree.setVisible(state, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class SubmissionListener implements FormSubmissionListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void submitted(final FormSectionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (event.getSource() == flatItemList.getManipulator()
|
|
||||||
.getTargetSelector()) {
|
|
||||||
if (!flatItemList.getManipulator().getTargetSelector()
|
|
||||||
.isVisible(state)) {
|
|
||||||
tree.setVisible(state, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class FolderListener implements ActionListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (!selectionModel.isSelected(state)) {
|
|
||||||
final String folder = state
|
|
||||||
.getRequest()
|
|
||||||
.getParameter(ContentSectionPage.SET_FOLDER);
|
|
||||||
|
|
||||||
if (folder == null) {
|
|
||||||
final Category root = CMS
|
|
||||||
.getContext()
|
|
||||||
.getContentSection()
|
|
||||||
.getRootDocumentsFolder();
|
|
||||||
final Long folderID = root.getObjectId();
|
|
||||||
|
|
||||||
/*
|
|
||||||
ToDo
|
|
||||||
User user = Web.getWebContext().getUser();
|
|
||||||
if (user != null) {
|
|
||||||
Folder homeFolder = Folder.getUserHomeFolder(
|
|
||||||
user, CMS.getContext().getContentSection());
|
|
||||||
if (homeFolder != null) {
|
|
||||||
folderID = homeFolder.getID();
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
selectionModel.setSelectedKey(state, folderID);
|
|
||||||
} else {
|
|
||||||
selectionModel.setSelectedKey(state, Long.parseLong(folder));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class TreeListener implements ActionListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Category root = CMS
|
|
||||||
.getContext()
|
|
||||||
.getContentSection()
|
|
||||||
.getRootDocumentsFolder();
|
|
||||||
|
|
||||||
if (!root.equals(folderRequestLocal.getFolder(state))) {
|
|
||||||
// Expand the ancestor nodes of the currently
|
|
||||||
// selected node.
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final FolderTreeModelController controller = cdiUtil.findBean(
|
|
||||||
FolderTreeModelController.class);
|
|
||||||
final List<Long> ancestorIds = controller.findAncestorIds(
|
|
||||||
folderRequestLocal.getFolder(state));
|
|
||||||
ancestorIds.forEach(id -> tree.expand(id.toString(), state));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BebopConfig;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.page.PageTransformer;
|
|
||||||
import com.arsdigita.cms.dispatcher.Utilities;
|
|
||||||
import com.arsdigita.templating.PresentationManager;
|
|
||||||
import com.arsdigita.xml.Document;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.Shiro;
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A <tt>CMSApplicationPage</tt> is a Bebop {@link com.arsdigita.bebop.Page}
|
|
||||||
* implementation serving as a base for any CMS pageElement served by a servlet.
|
|
||||||
*
|
|
||||||
* It stores the current {@link com.arsdigita.cms.ContentSection} and, if
|
|
||||||
* applicable, the {@link com.arsdigita.cms.ContentItem} in the pageElement
|
|
||||||
* state as request local objects. Components that are part of the
|
|
||||||
* <tt>CMSPage</tt> may access these objects by calling:
|
|
||||||
* <blockquote><code><pre>
|
|
||||||
* getContentSection(PageState state);
|
|
||||||
* </pre></code></blockquote>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @author Uday Mathur (umathur@arsdigita.com)
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class CMSApplicationPage extends Page {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
CMSApplicationPage.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The global assets URL stub XML parameter name.
|
|
||||||
*/
|
|
||||||
public final static String ASSETS = "ASSETS";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The XML pageElement class.
|
|
||||||
*/
|
|
||||||
public final static String PAGE_CLASS = "CMS";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map of XML parameters
|
|
||||||
*/
|
|
||||||
private Map<String, String> parameters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private PageTransformer pageTransformer;
|
|
||||||
|
|
||||||
public CMSApplicationPage() {
|
|
||||||
super();
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSApplicationPage(final String title) {
|
|
||||||
super(title);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSApplicationPage(final String title, final Container panel) {
|
|
||||||
super(title, panel);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSApplicationPage(final Label title) {
|
|
||||||
super(title);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSApplicationPage(final Label title, final Container panel) {
|
|
||||||
super(title, panel);
|
|
||||||
buildPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the pageElement.
|
|
||||||
*/
|
|
||||||
private void buildPage() {
|
|
||||||
|
|
||||||
// Set the class attribute value (down in SimpleComponent).
|
|
||||||
setClassAttr(PAGE_CLASS);
|
|
||||||
|
|
||||||
// Global XML params.
|
|
||||||
// MP: This only works with older versions of Xalan.
|
|
||||||
parameters = new HashMap<>();
|
|
||||||
setXMLParameter(ASSETS, Utilities.getGlobalAssetsURL());
|
|
||||||
|
|
||||||
// MP: This is a hack to so that the XML params work with the newer
|
|
||||||
// version of Xalan.
|
|
||||||
setAttribute(ASSETS, Utilities.getGlobalAssetsURL());
|
|
||||||
|
|
||||||
// Make sure the error display gets rendered.
|
|
||||||
getErrorDisplay().setIdAttr("page-body");
|
|
||||||
|
|
||||||
final Class<PresentationManager> presenterClass = BebopConfig
|
|
||||||
.getConfig()
|
|
||||||
.getPresenterClass();
|
|
||||||
final PresentationManager presenter;
|
|
||||||
try {
|
|
||||||
presenter = presenterClass.getDeclaredConstructor().newInstance();
|
|
||||||
} catch (InstantiationException
|
|
||||||
| IllegalAccessException
|
|
||||||
| NoSuchMethodException
|
|
||||||
| InvocationTargetException ex) {
|
|
||||||
throw new RuntimeException("Failed to create PresentationManager",
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presenter instanceof PageTransformer) {
|
|
||||||
pageTransformer = (PageTransformer) presenter;
|
|
||||||
} else {
|
|
||||||
pageTransformer = new PageTransformer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes and locks the pageElement. If the pageElement is already locked,
|
|
||||||
* does nothing.
|
|
||||||
*
|
|
||||||
* Client classes may overwrite this method to add context specific bits to
|
|
||||||
* the page before it is locked.
|
|
||||||
*
|
|
||||||
* This method is called by the various servlets serving the various pages
|
|
||||||
* of the CMS package, before serving and displaying the page.
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param app
|
|
||||||
*/
|
|
||||||
public synchronized void init(final HttpServletRequest request,
|
|
||||||
final HttpServletResponse response,
|
|
||||||
final CcmApplication app) {
|
|
||||||
LOGGER.debug("Initializing the page");
|
|
||||||
|
|
||||||
if (!isLocked()) {
|
|
||||||
LOGGER.debug("The page hasn't been locked; locking it now");
|
|
||||||
|
|
||||||
lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the value of the XML parameter.
|
|
||||||
*
|
|
||||||
* @param name The parameter name
|
|
||||||
*
|
|
||||||
* @return The parameter value
|
|
||||||
*
|
|
||||||
* @pre (name != null)
|
|
||||||
*/
|
|
||||||
public String getXMLParameter(final String name) {
|
|
||||||
return parameters.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an XML parameter.
|
|
||||||
*
|
|
||||||
* @param name The parameter name
|
|
||||||
* @param value The parameter value
|
|
||||||
*
|
|
||||||
* @pre (name != null)
|
|
||||||
*/
|
|
||||||
public void setXMLParameter(String name, String value) {
|
|
||||||
parameters.put(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwrites bebop.Page#generateXMLHelper to add the name of the user
|
|
||||||
* logged in to the pageElement (displayed as part of the header).
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
* @param parent
|
|
||||||
*
|
|
||||||
* @return pageElement for use in generateXML
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Element generateXMLHelper(final PageState state,
|
|
||||||
final Document parent) {
|
|
||||||
|
|
||||||
/* Retain elements already included. */
|
|
||||||
Element pageElement = super.generateXMLHelper(state, parent);
|
|
||||||
|
|
||||||
/* Add name of user logged in. */
|
|
||||||
// Note: There are at least 2 ways in the API to determin the user
|
|
||||||
// TODO: Check for differences, determin the best / recommended way and
|
|
||||||
// document it in the classes. Probably remove one ore the other
|
|
||||||
// way from the API if possible.
|
|
||||||
final Shiro shiro = CdiUtil.createCdiUtil().findBean(Shiro.class);
|
|
||||||
final Optional<User> user = shiro.getUser();
|
|
||||||
// User user = Web.getWebContext().getUser();
|
|
||||||
if (user.isPresent()) {
|
|
||||||
pageElement.addAttribute("name", user.get().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple container with XML wrapper tags.
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class CMSContainer extends SimpleContainer {
|
|
||||||
|
|
||||||
public final static String CMS_XML_NS = "http://www.arsdigita.com/cms/1.0";
|
|
||||||
|
|
||||||
|
|
||||||
public CMSContainer() {
|
|
||||||
super("cms:container", CMS_XML_NS);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.form.DHTMLEditor;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
|
|
||||||
import org.librecms.CMSConfig;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CMSDHTMLEditor extends DHTMLEditor {
|
|
||||||
|
|
||||||
public CMSDHTMLEditor(final String name) {
|
|
||||||
super(new StringParameter(name),
|
|
||||||
CMSConfig.getConfig().getDHTMLEditorConfig());
|
|
||||||
addPlugins();
|
|
||||||
hideButtons();
|
|
||||||
|
|
||||||
final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
final GlobalizationHelper globalizationHelper = CdiUtil
|
|
||||||
.createCdiUtil()
|
|
||||||
.findBean(GlobalizationHelper.class);
|
|
||||||
setAttribute("current-contentsection-id",
|
|
||||||
Long.toString(section.getObjectId()));
|
|
||||||
setAttribute("current-contentsection-primaryurl",
|
|
||||||
section.getPrimaryUrl());
|
|
||||||
setAttribute("current-contentsection-title",
|
|
||||||
globalizationHelper
|
|
||||||
.getValueFromLocalizedString(section.getTitle()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSDHTMLEditor(final ParameterModel model) {
|
|
||||||
super(model,
|
|
||||||
CMSConfig.getConfig().getDHTMLEditorConfig());
|
|
||||||
|
|
||||||
addPlugins();
|
|
||||||
hideButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addPlugins() {
|
|
||||||
|
|
||||||
CMSConfig
|
|
||||||
.getConfig()
|
|
||||||
.getDhtmlEditorPlugins()
|
|
||||||
.forEach(plugin -> addPlugin(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hideButtons() {
|
|
||||||
|
|
||||||
CMSConfig
|
|
||||||
.getConfig()
|
|
||||||
.getDhtmlEditorHiddenButtons()
|
|
||||||
.forEach(hiddenButton -> hideButton(hiddenButton));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.toolbox.ui.Cancellable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience class for CMS forms. The "CMS Admin" class eliminates
|
|
||||||
* the nested tables created by the Bebop ColumnPanel. This is mainly
|
|
||||||
* to increase form rendering.
|
|
||||||
*
|
|
||||||
* @author Michael Pih
|
|
||||||
*/
|
|
||||||
public class CMSForm extends Form implements Cancellable {
|
|
||||||
|
|
||||||
public static final String CLASS = "CMS Admin";
|
|
||||||
|
|
||||||
public CMSForm(final String name) {
|
|
||||||
super(name);
|
|
||||||
|
|
||||||
setClassAttr(CLASS);
|
|
||||||
getPanel().setClassAttr(CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CMSForm(final String name, final Container panel) {
|
|
||||||
super(name, panel);
|
|
||||||
|
|
||||||
setClassAttr(CLASS);
|
|
||||||
panel.setClassAttr(CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the form has been cancelled.
|
|
||||||
* Override this method if the form can be cancelled.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @return true if the form is cancelled, false otherwise
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled(final PageState state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,481 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.*;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.OptionGroup;
|
|
||||||
import com.arsdigita.bebop.form.SingleSelect;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
||||||
import com.arsdigita.bebop.util.GlobalizationUtil;
|
|
||||||
import com.arsdigita.bebop.util.SequentialMap;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.ui.authoring.BasicItemForm;
|
|
||||||
import com.arsdigita.globalization.Globalization;
|
|
||||||
import com.arsdigita.util.StringUtils;
|
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.categorization.Category;
|
|
||||||
import org.libreccm.categorization.CategoryManager;
|
|
||||||
import org.libreccm.categorization.CategoryRepository;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.core.CcmObject;
|
|
||||||
|
|
||||||
import javax.enterprise.inject.spi.CDI;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an abstract class which displays the category assignment UI.
|
|
||||||
*
|
|
||||||
* Displays two listboxes for assigning categories to items, with two
|
|
||||||
* submit buttons to move categories back and forth. The left
|
|
||||||
* listbox displays all available categories which have not been
|
|
||||||
* assigned to the current item. The right listbox displays all categories
|
|
||||||
* assigned to the current item.
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Stanislav Freidin (sfreidin@arsdigita.com)
|
|
||||||
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
|
|
||||||
*/
|
|
||||||
public abstract class CategoryForm extends Form
|
|
||||||
implements FormProcessListener, FormValidationListener {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
CategoryForm.class);
|
|
||||||
private static final String SEPARATOR = ">";
|
|
||||||
public static final String FREE = "free";
|
|
||||||
public static final String ASSIGNED = "assigned";
|
|
||||||
public static final String ASSIGN = "assign";
|
|
||||||
public static final String REMOVE = "remove";
|
|
||||||
public static final int SELECT_WIDTH = 30;
|
|
||||||
public static final int SELECT_HEIGHT = 10;
|
|
||||||
public static final String FILLER_OPTION = StringUtils.repeat("_", SELECT_WIDTH);
|
|
||||||
|
|
||||||
private final RequestLocal m_assigned;
|
|
||||||
private Submit m_assign, m_remove;
|
|
||||||
|
|
||||||
private final Label m_freeLabel;
|
|
||||||
private final Label m_assignedLabel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new CategoryForm component
|
|
||||||
*
|
|
||||||
* @param name the name of the form
|
|
||||||
*/
|
|
||||||
public CategoryForm(String name) {
|
|
||||||
super(name, new ColumnPanel(3));
|
|
||||||
|
|
||||||
ColumnPanel panel = (ColumnPanel) getPanel();
|
|
||||||
panel.setBorder(false);
|
|
||||||
panel.setPadColor("#FFFFFF");
|
|
||||||
panel.setColumnWidth(1, "0%");
|
|
||||||
panel.setColumnWidth(2, "0%");
|
|
||||||
panel.setColumnWidth(3, "0");
|
|
||||||
panel.setWidth("0%");
|
|
||||||
panel.setClassAttr("CMS Admin");
|
|
||||||
|
|
||||||
// Create the request local
|
|
||||||
m_assigned = new RequestLocal() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object initialValue(PageState state) {
|
|
||||||
CategoryMap m = new CategoryMap();
|
|
||||||
initAssignedCategories(state, m);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Top row
|
|
||||||
m_freeLabel = new Label(GlobalizationUtil.globalize("cms.ui.item.categories.available"), false);
|
|
||||||
m_freeLabel.setFontWeight(Label.BOLD);
|
|
||||||
add(m_freeLabel, ColumnPanel.LEFT);
|
|
||||||
|
|
||||||
//add(new Label(" ", false));
|
|
||||||
add(new Embedded(" ", false));
|
|
||||||
|
|
||||||
m_assignedLabel = new Label(GlobalizationUtil.globalize("cms.ui.item.categories.assigned"), false);
|
|
||||||
m_assignedLabel.setFontWeight(Label.BOLD);
|
|
||||||
add(m_assignedLabel, ColumnPanel.LEFT);
|
|
||||||
|
|
||||||
// Middle Row
|
|
||||||
SingleSelect freeWidget = new SingleSelect(new BigDecimalParameter(FREE));
|
|
||||||
try {
|
|
||||||
freeWidget.addPrintListener(new FreePrintListener());
|
|
||||||
} catch (TooManyListenersException e) {
|
|
||||||
UncheckedWrapperException.throwLoggedException(getClass(), "Too many listeners", e);
|
|
||||||
}
|
|
||||||
freeWidget.setSize(SELECT_HEIGHT);
|
|
||||||
add(freeWidget);
|
|
||||||
|
|
||||||
BoxPanel box = new BoxPanel(BoxPanel.VERTICAL, true);
|
|
||||||
box.setWidth("2%");
|
|
||||||
addSubmitButtons(box);
|
|
||||||
add(box, ColumnPanel.CENTER | ColumnPanel.MIDDLE);
|
|
||||||
|
|
||||||
SingleSelect assignedWidget =
|
|
||||||
new SingleSelect(new BigDecimalParameter(ASSIGNED));
|
|
||||||
try {
|
|
||||||
assignedWidget.addPrintListener(new AssignedPrintListener());
|
|
||||||
} catch (TooManyListenersException e) {
|
|
||||||
UncheckedWrapperException.throwLoggedException(getClass(), "Too many listeners", e);
|
|
||||||
}
|
|
||||||
assignedWidget.setSize(SELECT_HEIGHT);
|
|
||||||
add(assignedWidget);
|
|
||||||
|
|
||||||
// Add listeners
|
|
||||||
addProcessListener(this);
|
|
||||||
addValidationListener(this);
|
|
||||||
|
|
||||||
setClassAttr("CategoryForm");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addSubmitButtons(Container c) {
|
|
||||||
addAssignButton(c);
|
|
||||||
addRemoveButton(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addAssignButton(Container c) {
|
|
||||||
m_assign = new Submit(ASSIGN, ">>");
|
|
||||||
m_assign.setSize(10);
|
|
||||||
c.add(m_assign);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addRemoveButton(Container c) {
|
|
||||||
m_remove = new Submit(REMOVE, "<<");
|
|
||||||
m_remove.setSize(10);
|
|
||||||
c.add(m_remove);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the caption of the unassigned categories label
|
|
||||||
*
|
|
||||||
* @param caption the new caption
|
|
||||||
*/
|
|
||||||
public void setUnassignedCaption(String caption) {
|
|
||||||
m_freeLabel.setLabel(caption);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the caption of the assigned categories label
|
|
||||||
*
|
|
||||||
* @param caption the new caption
|
|
||||||
*/
|
|
||||||
public void setAssignedCaption(String caption) {
|
|
||||||
m_assignedLabel.setLabel(caption);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param s the page state
|
|
||||||
* @return a {@link CategoryMap} of all assigned categories
|
|
||||||
*/
|
|
||||||
public CategoryMap getAssignedCategories(PageState s) {
|
|
||||||
return (CategoryMap) m_assigned.get(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A print listener which populates the listbox with all
|
|
||||||
// unassigned categories, apart from result of getExcludedCategory()
|
|
||||||
// (if not null), and the root category.
|
|
||||||
// Ordering is alphabetical based on qualified path, so entries are
|
|
||||||
// ordered like a tree with all nodes expanded.
|
|
||||||
// Ideally ordering should be like an expanded tree but based on
|
|
||||||
// the sortkey order of the categories. However, I don't know
|
|
||||||
// if it would be possible to write a comparison function that
|
|
||||||
// could do this efficiently, and I'm not even going to try
|
|
||||||
// chris.gilbert@westsussex.gov.uk
|
|
||||||
//
|
|
||||||
private class FreePrintListener implements PrintListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(PrintEvent e) {
|
|
||||||
|
|
||||||
OptionGroup target = (OptionGroup) e.getTarget();
|
|
||||||
target.clearOptions();
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
// Category root = getRootCategory(state);
|
|
||||||
// if (root == null) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// exclude children of the excluded category (as per javadoc on
|
|
||||||
// getExcludedCategory() method. This prevents attempts
|
|
||||||
// to create circular category graph (which causes
|
|
||||||
// exception in Category during addMapping if not checked here
|
|
||||||
Category excludedCat = getExcludedCategory(state);
|
|
||||||
CategoryMap excluded = new CategoryMap();
|
|
||||||
if (excludedCat != null) {
|
|
||||||
java.util.List<Category> excludedSubTree = getExcludedCategory(state).getSubCategories();
|
|
||||||
excludedSubTree.forEach(excluded::add);
|
|
||||||
}
|
|
||||||
CategoryMap assigned = getAssignedCategories(state);
|
|
||||||
SortedMap sortedCats = new TreeMap();
|
|
||||||
// java.util.List<Category> children = root.getSubCategories();
|
|
||||||
// children.forEach(x -> sortedCats.put(x.getName(), x.getUniqueId()));
|
|
||||||
|
|
||||||
Iterator it = sortedCats.entrySet().iterator();
|
|
||||||
Map.Entry entry;
|
|
||||||
String path;
|
|
||||||
String id;
|
|
||||||
boolean notExcluded;
|
|
||||||
boolean notAlreadyAssigned;
|
|
||||||
// boolean notRoot;
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
entry = (Map.Entry) it.next();
|
|
||||||
path = (String) entry.getKey();
|
|
||||||
id = (String) entry.getValue();
|
|
||||||
|
|
||||||
notExcluded = !excluded.containsKey(id);
|
|
||||||
notAlreadyAssigned = !assigned.containsKey(id);
|
|
||||||
// notRoot = !id.equals(root.getUniqueId());
|
|
||||||
|
|
||||||
if (notExcluded && notAlreadyAssigned) {// && notRoot) {
|
|
||||||
target.addOption(new Option(id, new Text(path)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
addFillerOption(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate a {@link CategoryMap} with all categories which are assigned to
|
|
||||||
* the item. Child classes should override this method to do the right thing.
|
|
||||||
*
|
|
||||||
* @param map The sequential map of all categories which are assigned to
|
|
||||||
* the current item. Overridden method should repeatedly
|
|
||||||
* <code>call map.addCategory(someCategory);</code>
|
|
||||||
* @param state The page state
|
|
||||||
*/
|
|
||||||
protected abstract void initAssignedCategories(PageState state, CategoryMap map);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assign a category, moving it from the list on the left
|
|
||||||
* to the list on the right
|
|
||||||
*
|
|
||||||
* @param s the page state
|
|
||||||
* @param cat the category to assign
|
|
||||||
*/
|
|
||||||
protected abstract void assignCategory(PageState s, Category cat);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unassign a category, moving it from the list on the right
|
|
||||||
* to the list on the left
|
|
||||||
*
|
|
||||||
* @param s the page state
|
|
||||||
* @param cat the category to unassign
|
|
||||||
*/
|
|
||||||
protected abstract void unassignCategory(PageState s, Category cat);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the URL for the givne item to make sure that
|
|
||||||
* the item it is not possible to have two objects in the same category
|
|
||||||
* with the same URL.
|
|
||||||
* @param state The Page State
|
|
||||||
*/
|
|
||||||
protected abstract String getItemURL(PageState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This allows the validation code to validate the properties of the
|
|
||||||
* object
|
|
||||||
*/
|
|
||||||
protected abstract CcmObject getObject(PageState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the category which will act as the root for the lists
|
|
||||||
* of assigned and unassigned categories. The default implementation
|
|
||||||
* returns the root category for the content section. Child classes
|
|
||||||
* should override this method if they wish to provide an alternate root category.
|
|
||||||
*
|
|
||||||
* @param state the page state
|
|
||||||
* @return the root category which should be used to populate the lists
|
|
||||||
* of assigned and unassigned categories
|
|
||||||
*/
|
|
||||||
// public Category getRootCategory(PageState state) {
|
|
||||||
// return null;
|
|
||||||
// return CMS.getContext().getContentSection().getRootCategory();
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a category which should be excluded from the list of
|
|
||||||
* free categories. It is permissible to return null
|
|
||||||
*
|
|
||||||
* @param s the page state
|
|
||||||
* @return a category whose subtree will not be shown in the
|
|
||||||
* category list
|
|
||||||
*/
|
|
||||||
protected Category getExcludedCategory(PageState s) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populates the "assigned categories" widget
|
|
||||||
@Deprecated
|
|
||||||
private class AssignedPrintListener implements PrintListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(PrintEvent e) {
|
|
||||||
OptionGroup o = (OptionGroup) e.getTarget();
|
|
||||||
o.clearOptions();
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
CategoryMap m = getAssignedCategories(state);
|
|
||||||
|
|
||||||
if (!m.isEmpty()) {
|
|
||||||
for (Iterator i = m.values().iterator(); i.hasNext();) {
|
|
||||||
Category c = (Category) i.next();
|
|
||||||
o.addOption(new Option(c.getUniqueId(), new Text(getCategoryPath(c))));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
o.addOption(new Option("", new Text("-- none --")));
|
|
||||||
}
|
|
||||||
|
|
||||||
addFillerOption(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the form: assign/unassign categories
|
|
||||||
@Override
|
|
||||||
public void process(FormSectionEvent e) throws FormProcessException {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final CategoryRepository categoryRepository = cdiUtil.findBean(CategoryRepository.class);
|
|
||||||
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
FormData data = e.getFormData();
|
|
||||||
Long id;
|
|
||||||
|
|
||||||
if (m_assign.isSelected(state)) {
|
|
||||||
id = ((BigDecimal) data.get(FREE)).longValue();
|
|
||||||
Optional<Category> optional = categoryRepository.findById(id);
|
|
||||||
if (optional.isPresent()) {
|
|
||||||
Category cat = optional.get();
|
|
||||||
assignCategory(state, cat);
|
|
||||||
data.put(ASSIGNED, id);
|
|
||||||
} else {
|
|
||||||
throw new FormProcessException(GlobalizationUtil.globalize(String.format("Can't find category with id %d", id)));
|
|
||||||
}
|
|
||||||
} else if (m_remove.isSelected(state)) {
|
|
||||||
id = ((BigDecimal) data.get(ASSIGNED)).longValue();
|
|
||||||
Optional<Category> optional = categoryRepository.findById(id);
|
|
||||||
if (optional.isPresent()) {
|
|
||||||
Category cat = optional.get();
|
|
||||||
unassignCategory(state, cat);
|
|
||||||
data.put(FREE, id);
|
|
||||||
} else {
|
|
||||||
throw new FormProcessException(GlobalizationUtil.globalize(String.format("Can't find category with id %d", id)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the form: make sure that a category is selected
|
|
||||||
// for the remove/assign buttons
|
|
||||||
@Override
|
|
||||||
public void validate(FormSectionEvent e) throws FormProcessException {
|
|
||||||
PageState state = e.getPageState();
|
|
||||||
FormData data = e.getFormData();
|
|
||||||
if (m_assign.isSelected(state)) {
|
|
||||||
if (data.get(FREE) == null) {
|
|
||||||
data.addError(GlobalizationUtil.globalize("cms.ui.category.assign_select_missing"));
|
|
||||||
} else {
|
|
||||||
// we need to make sure that no other item in this
|
|
||||||
// category has the same name (url)
|
|
||||||
Long id = ((BigDecimal) data.get(FREE)).longValue();
|
|
||||||
|
|
||||||
// Assign a new category
|
|
||||||
// try {
|
|
||||||
// String url = getItemURL(state);
|
|
||||||
//
|
|
||||||
// if (url != null) {
|
|
||||||
// DataQuery query = SessionManager.getSession().retrieveQuery("com.arsdigita.categorization.getAllItemURLsForCategory");
|
|
||||||
// query.setParameter("categoryID", id);
|
|
||||||
// query.addEqualsFilter("lower(url)", url.toLowerCase());
|
|
||||||
//
|
|
||||||
// if (query.size() > 0) {
|
|
||||||
// // we need to make sure that there is not an item
|
|
||||||
// ACSObject item = getObject(state);
|
|
||||||
// Collection list;
|
|
||||||
// if (item instanceof ContentItem) {
|
|
||||||
// list = BasicItemForm.getAllVersionIDs((ContentItem) item);
|
|
||||||
// } else {
|
|
||||||
// list = new ArrayList();
|
|
||||||
// list.add(item.getID());
|
|
||||||
// }
|
|
||||||
// BigDecimal itemID;
|
|
||||||
// while (query.next()) {
|
|
||||||
// itemID = (BigDecimal) query.get("itemID");
|
|
||||||
// if (!list.contains(itemID)) {
|
|
||||||
// data.addError("There is already an item "
|
|
||||||
// + "with the url " + url
|
|
||||||
// + " in the category "
|
|
||||||
// + cat.getName());
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (DataObjectNotFoundException ex) {
|
|
||||||
// s_log.error("Error processing category. Unable to find "
|
|
||||||
// + "category with id " + id);
|
|
||||||
// throw new FormProcessException(ex);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
} else if (m_remove.isSelected(state)) {
|
|
||||||
if (data.get(ASSIGNED) == null) {
|
|
||||||
data.addError(GlobalizationUtil.globalize("cms.ui.category.assign_select_missing"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a "filler" option to the option group in order to ensure
|
|
||||||
// the correct horizontal width
|
|
||||||
private static void addFillerOption(OptionGroup o) {
|
|
||||||
o.addOption(new Option("", FILLER_OPTION));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the full path to a category
|
|
||||||
*/
|
|
||||||
public static String getCategoryPath(Category c) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final CategoryManager categoryManager = cdiUtil.findBean(CategoryManager.class);
|
|
||||||
return categoryManager.getCategoryPath(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience method that abstracts SequentialMap
|
|
||||||
* to deal with categories
|
|
||||||
*/
|
|
||||||
protected static class CategoryMap extends SequentialMap {
|
|
||||||
|
|
||||||
public CategoryMap() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(Category c) {
|
|
||||||
super.put(c.getUniqueId(), c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
|
|
||||||
import org.libreccm.core.CcmObject;
|
|
||||||
|
|
||||||
|
|
||||||
public class CcmObjectRequestLocal extends RequestLocal {
|
|
||||||
|
|
||||||
public final CcmObject getACSObject(final PageState state) {
|
|
||||||
return (CcmObject) get(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.PageLocations;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.contentsection.ContentItemL10NManager;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* The context bar of the content section UI.</p>
|
|
||||||
*
|
|
||||||
* @author Justin Ross
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
class ContentItemContextBar extends ContentSectionContextBar {
|
|
||||||
|
|
||||||
private final ItemSelectionModel itemSelectionModel;
|
|
||||||
private final StringParameter selectedLanguageParam;
|
|
||||||
|
|
||||||
ContentItemContextBar(final ItemSelectionModel itemSelectionModel,
|
|
||||||
final StringParameter selectedLanguageParam) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.itemSelectionModel = itemSelectionModel;
|
|
||||||
this.selectedLanguageParam = selectedLanguageParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final List<Entry> entries(final PageState state) {
|
|
||||||
final List<Entry> entries = super.entries(state);
|
|
||||||
final ContentItem item = itemSelectionModel.getSelectedObject(state);
|
|
||||||
final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
|
|
||||||
final URL url = URL.there(state.getRequest(),
|
|
||||||
section.getPrimaryUrl() + "/"
|
|
||||||
+ PageLocations.ITEM_PAGE,
|
|
||||||
params(item));
|
|
||||||
|
|
||||||
final StringBuilder title = new StringBuilder();
|
|
||||||
title.append(localize("cms.ui.content_item"));
|
|
||||||
title.append(": ")
|
|
||||||
.append(item.getDisplayName());
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentItemL10NManager l10nManager = cdiUtil
|
|
||||||
.findBean(ContentItemL10NManager.class);
|
|
||||||
final String selectedLanguage = (String) state
|
|
||||||
.getValue(selectedLanguageParam);
|
|
||||||
final Locale selectedLocale;
|
|
||||||
if (selectedLanguage == null
|
|
||||||
|| selectedLanguage.isEmpty()) {
|
|
||||||
selectedLocale = KernelConfig.getConfig().getDefaultLocale();
|
|
||||||
} else {
|
|
||||||
selectedLocale = new Locale(selectedLanguage);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String language;
|
|
||||||
if (l10nManager.hasLanguage(item, selectedLocale)) {
|
|
||||||
language = selectedLanguage;
|
|
||||||
} else {
|
|
||||||
state.setValue(selectedLanguageParam,
|
|
||||||
KernelConfig.getConfig().getDefaultLanguage());
|
|
||||||
language = KernelConfig.getConfig().getDefaultLanguage();
|
|
||||||
}
|
|
||||||
if (language != null) {
|
|
||||||
title.append(" (")
|
|
||||||
.append(language)
|
|
||||||
.append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.add(new Entry(title.toString(), url));
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ParameterMap params(final ContentItem item) {
|
|
||||||
final ParameterMap params = new ParameterMap();
|
|
||||||
|
|
||||||
params.setParameter(ContentItemPage.ITEM_ID, item.getObjectId());
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String localize(final String key) {
|
|
||||||
return (String) ContentSectionPage.globalize(key).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,698 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Link;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.TabbedPane;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.parameters.LongParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.ItemSelectionModel;
|
|
||||||
import com.arsdigita.cms.PageLocations;
|
|
||||||
import com.arsdigita.cms.dispatcher.CMSPage;
|
|
||||||
import com.arsdigita.cms.ui.authoring.WizardSelector;
|
|
||||||
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
|
|
||||||
import com.arsdigita.cms.ui.item.CustomizedPreviewLink;
|
|
||||||
import com.arsdigita.cms.ui.item.ItemLanguages;
|
|
||||||
import com.arsdigita.cms.ui.item.Summary;
|
|
||||||
import com.arsdigita.cms.ui.lifecycle.ItemLifecycleAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.revision.ItemRevisionAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.templates.ItemTemplates;
|
|
||||||
import com.arsdigita.cms.ui.workflow.ItemWorkflowAdminPane;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.xml.Document;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.librecms.CMSConfig;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentItemL10NManager;
|
|
||||||
import org.librecms.contentsection.ContentItemRepository;
|
|
||||||
import org.librecms.contentsection.ContentItemVersion;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentType;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Page for administering a content item.
|
|
||||||
*
|
|
||||||
* @author Michael Pih
|
|
||||||
* @author <a href="mailto:sfreidin@redhat.com">Stanislav Freidin</a>
|
|
||||||
* @author Jack Chung
|
|
||||||
* @author <a href="mailto:quasi@quasiweb.de">Sören Bernstein</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ContentItemPage extends CMSPage implements ActionListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private Logger instance for debugging purpose.
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
ContentItemPage.class);
|
|
||||||
/**
|
|
||||||
* The URL parameter that must be passed in in order to set the current tab.
|
|
||||||
* This is a KLUDGE right now because the TabbedDialog's current tab is
|
|
||||||
* selected with a local state parameter
|
|
||||||
*/
|
|
||||||
public static final String SET_TAB = "set_tab";
|
|
||||||
/**
|
|
||||||
* The name of the global state parameter that holds the item id.
|
|
||||||
*/
|
|
||||||
public static final String ITEM_ID = "item_id";
|
|
||||||
/**
|
|
||||||
* The name of th global state parameter that holds the selected language.
|
|
||||||
*/
|
|
||||||
public static final String SELECTED_LANGUAGE = "selected_language";
|
|
||||||
/**
|
|
||||||
* The name of the global state parameter which holds the return URL.
|
|
||||||
*/
|
|
||||||
public static final String RETURN_URL = "return_url";
|
|
||||||
/**
|
|
||||||
* The name of the global state parameter that determines whether or not to
|
|
||||||
* use the streamlined authoring process (assuming the option is turned on).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static final String STREAMLINED_CREATION = "streamlined_creation";
|
|
||||||
public static final String STREAMLINED_CREATION_ACTIVE = "active";
|
|
||||||
public static final String STREAMLINED_CREATION_INACTIVE = "active";
|
|
||||||
/**
|
|
||||||
* Index of the summary tab
|
|
||||||
*/
|
|
||||||
public static final int SUMMARY_TAB = 0;
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* The name of the state parameter which indicates the content type of the
|
|
||||||
* item the user wishes to create. or edit.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The parameter must be a BigDecimalParameter which encodes the id of the
|
|
||||||
* content type.</p>
|
|
||||||
*/
|
|
||||||
public static final String CONTENT_TYPE = "content_type";
|
|
||||||
public static final int AUTHORING_TAB = 1;
|
|
||||||
public static final int LANGUAGE_TAB = 2;
|
|
||||||
public static final int WORKFLOW_TAB = 3;
|
|
||||||
public static final int PUBLISHING_TAB = 4;
|
|
||||||
public static final int HISTORY_TAB = 5;
|
|
||||||
public static final int TEMPLATES_TAB = 6;
|
|
||||||
|
|
||||||
private final TabbedPane tabbedPane;
|
|
||||||
private final StringParameter returnUrlParameter;
|
|
||||||
private final ItemSelectionModel itemSelectionModel;
|
|
||||||
// private final SingleSelectionModel<String> selectedLanguageModel;
|
|
||||||
private final ACSObjectSelectionModel typeSelectionModel;
|
|
||||||
private final ContentItemRequestLocal itemRequestLocal;
|
|
||||||
private final Summary summaryPane;
|
|
||||||
private final ItemWorkflowAdminPane workflowPane;
|
|
||||||
private final ItemLifecycleAdminPane lifecyclePane;
|
|
||||||
private final WizardSelector wizardPane;
|
|
||||||
private final ItemLanguages languagesPane;
|
|
||||||
private final ItemRevisionAdminPane revisionsPane;
|
|
||||||
private final ItemTemplates templatesPane;
|
|
||||||
private final Link previewLink;
|
|
||||||
private final GlobalNavigation globalNavigation;
|
|
||||||
private final ContentItemContextBar contextBar;
|
|
||||||
|
|
||||||
private final StringParameter selectedLanguageParam;
|
|
||||||
|
|
||||||
private class ItemRequestLocal extends ContentItemRequestLocal {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final Object initialValue(final PageState state) {
|
|
||||||
return CMS.getContext().getContentItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TitlePrinter implements PrintListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void prepare(final PrintEvent event) {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Label label = (Label) event.getTarget();
|
|
||||||
final ContentItem item = itemRequestLocal.getContentItem(event.
|
|
||||||
getPageState());
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentItemL10NManager l10nManager = cdiUtil
|
|
||||||
.findBean(ContentItemL10NManager.class);
|
|
||||||
final String selectedLanguage = (String) state
|
|
||||||
.getValue(selectedLanguageParam);
|
|
||||||
final Locale selectedLocale;
|
|
||||||
if (selectedLanguage == null
|
|
||||||
|| selectedLanguage.isEmpty()) {
|
|
||||||
selectedLocale = KernelConfig.getConfig().getDefaultLocale();
|
|
||||||
} else {
|
|
||||||
selectedLocale = new Locale(selectedLanguage);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String language;
|
|
||||||
if (l10nManager.hasLanguage(item, selectedLocale)) {
|
|
||||||
language = selectedLanguage;
|
|
||||||
} else {
|
|
||||||
state.setValue(selectedLanguageParam,
|
|
||||||
KernelConfig.getConfig().getDefaultLanguage());
|
|
||||||
language = KernelConfig.getConfig().getDefaultLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
final StringBuffer title = new StringBuffer(item.getDisplayName());
|
|
||||||
if (language != null) {
|
|
||||||
title
|
|
||||||
.append(" (")
|
|
||||||
.append(language)
|
|
||||||
.append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
label.setLabel(title.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new ContentItemPage.
|
|
||||||
*/
|
|
||||||
public ContentItemPage() {
|
|
||||||
super("", new SimpleContainer());
|
|
||||||
|
|
||||||
itemRequestLocal = new ItemRequestLocal();
|
|
||||||
|
|
||||||
setClassAttr("cms-admin");
|
|
||||||
setTitle(new Label(new TitlePrinter()));
|
|
||||||
|
|
||||||
// Add the item id global state parameter
|
|
||||||
final LongParameter itemId = new LongParameter(ITEM_ID);
|
|
||||||
itemId.addParameterListener(new NotNullValidationListener(ITEM_ID));
|
|
||||||
addGlobalStateParam(itemId);
|
|
||||||
itemSelectionModel = new ItemSelectionModel(itemId);
|
|
||||||
|
|
||||||
// Add the selected item language as parameter
|
|
||||||
selectedLanguageParam = new StringParameter(SELECTED_LANGUAGE);
|
|
||||||
selectedLanguageParam.addParameterListener(
|
|
||||||
new NotNullValidationListener(SELECTED_LANGUAGE));
|
|
||||||
addGlobalStateParam(selectedLanguageParam);
|
|
||||||
// selectedLanguageModel = new ParameterSingleSelectionModel<>(
|
|
||||||
// selectedLanguageParam);
|
|
||||||
// selectedLanguageParam
|
|
||||||
// .setDefaultValue(KernelConfig.getConfig().getDefaultLanguage());
|
|
||||||
|
|
||||||
// Add the content type global state parameter
|
|
||||||
final LongParameter contentType = new LongParameter(CONTENT_TYPE);
|
|
||||||
addGlobalStateParam(contentType);
|
|
||||||
|
|
||||||
// Add the streamlined creation global state parameter
|
|
||||||
final StringParameter streamlinedCreation = new StringParameter(
|
|
||||||
STREAMLINED_CREATION);
|
|
||||||
addGlobalStateParam(streamlinedCreation);
|
|
||||||
|
|
||||||
typeSelectionModel = new ACSObjectSelectionModel(ContentType.class
|
|
||||||
.getName(),
|
|
||||||
ContentType.class
|
|
||||||
.getName(),
|
|
||||||
contentType);
|
|
||||||
|
|
||||||
// Validate the item ID parameter (caches the validation).
|
|
||||||
getStateModel().addValidationListener(
|
|
||||||
event -> validateItemID(event.getPageState()));
|
|
||||||
|
|
||||||
// Add the return url global state parameter
|
|
||||||
returnUrlParameter = new StringParameter(RETURN_URL);
|
|
||||||
addGlobalStateParam(returnUrlParameter);
|
|
||||||
|
|
||||||
globalNavigation = new GlobalNavigation();
|
|
||||||
add(globalNavigation);
|
|
||||||
|
|
||||||
contextBar = new ContentItemContextBar(itemSelectionModel,
|
|
||||||
selectedLanguageParam);
|
|
||||||
add(contextBar);
|
|
||||||
|
|
||||||
// Create panels.
|
|
||||||
summaryPane = new Summary(itemSelectionModel);
|
|
||||||
wizardPane = new WizardSelector(itemSelectionModel, typeSelectionModel);
|
|
||||||
languagesPane = new ItemLanguages(itemSelectionModel,
|
|
||||||
// selectedLanguageModel,
|
|
||||||
selectedLanguageParam);
|
|
||||||
workflowPane = new ItemWorkflowAdminPane(itemId); // Make this use m_item XXX
|
|
||||||
lifecyclePane = new ItemLifecycleAdminPane(itemRequestLocal);
|
|
||||||
revisionsPane = new ItemRevisionAdminPane(itemRequestLocal);
|
|
||||||
templatesPane = new ItemTemplates(itemSelectionModel);
|
|
||||||
|
|
||||||
// Create tabbed pane.
|
|
||||||
tabbedPane = new TabbedPane();
|
|
||||||
add(tabbedPane);
|
|
||||||
|
|
||||||
tabbedPane.setIdAttr("page-body");
|
|
||||||
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.summary")), summaryPane);
|
|
||||||
tabbedPane.
|
|
||||||
addTab(new Label(gz("cms.ui.item.authoring")), wizardPane);
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.languages")),
|
|
||||||
languagesPane);
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.workflow")),
|
|
||||||
workflowPane);
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.lifecycles")),
|
|
||||||
lifecyclePane);
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.history")),
|
|
||||||
revisionsPane);
|
|
||||||
tabbedPane.addTab(new Label(gz("cms.ui.item.templates")),
|
|
||||||
templatesPane);
|
|
||||||
|
|
||||||
tabbedPane.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void actionPerformed(final ActionEvent event) {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final Component pane = tabbedPane.getCurrentPane(state);
|
|
||||||
|
|
||||||
if (pane instanceof Resettable) {
|
|
||||||
((Resettable) pane).reset(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// Build the preview link.
|
|
||||||
previewLink = new Link(new Label(gz("cms.ui.preview")),
|
|
||||||
new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void prepare(
|
|
||||||
final PrintEvent event) {
|
|
||||||
final Link link = (Link) event.getTarget();
|
|
||||||
link.setTarget(getPreviewURL(event.
|
|
||||||
getPageState()));
|
|
||||||
link.setTargetFrame(Link.NEW_FRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
previewLink.setIdAttr("preview_link");
|
|
||||||
add(previewLink);
|
|
||||||
|
|
||||||
addActionListener(this);
|
|
||||||
|
|
||||||
// Add validation to make sure we are not attempting to edit a live item
|
|
||||||
getStateModel().addValidationListener(new FormValidationListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
PageState s = event.getPageState();
|
|
||||||
FormData data = event.getFormData();
|
|
||||||
final ContentItem item = itemRequestLocal.getContentItem(s);
|
|
||||||
if (item != null
|
|
||||||
&& ContentItemVersion.LIVE == item.getVersion()) {
|
|
||||||
LOGGER.error(String.format(
|
|
||||||
"The item %d is live and cannot be edited.", item.
|
|
||||||
getObjectId()));
|
|
||||||
throw new FormProcessException(new GlobalizedMessage(
|
|
||||||
"cms.ui.live_item_not_editable",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that the item_id parameter references a valid {@link
|
|
||||||
* com.arsdigita.cms.ContentItem}.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @pre state != null
|
|
||||||
* @exception FormProcessException if the item_id is not valid
|
|
||||||
*/
|
|
||||||
protected void validateItemID(final PageState state) throws
|
|
||||||
FormProcessException {
|
|
||||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
|
||||||
|
|
||||||
if (item == null) {
|
|
||||||
throw new FormProcessException(new GlobalizedMessage(
|
|
||||||
"cms.ui.invalid_item_id", CmsConstants.CMS_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
|
|
||||||
* instead
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content section
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ContentSection getContentSection(final HttpServletRequest request) {
|
|
||||||
// Resets all content sections associations.
|
|
||||||
ContentSection section = super.getContentSection(request);
|
|
||||||
Assert.exists(section);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides CMSPage.getContentItem(PageState state) to get the current
|
|
||||||
* content item from the page state.
|
|
||||||
*
|
|
||||||
* @deprecated Use the ItemSelectionModel
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return The current content item, null if there is none
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ContentItem getContentItem(final PageState state) {
|
|
||||||
return (ContentItem) itemSelectionModel.getSelectedObject(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the current tab, if necessary
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final String setTab = state.getRequest().getParameter(SET_TAB);
|
|
||||||
|
|
||||||
// Hide the templates tab, the workflow tab, and the preview
|
|
||||||
// link if the current item is a template.
|
|
||||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
|
||||||
|
|
||||||
// ToDo: Reenable when Templates have been ported. Not clear yet if
|
|
||||||
// Templates will be ContentItems in LibreCMS...
|
|
||||||
// if (item instanceof Template) {
|
|
||||||
// tabbedPane.setTabVisible(state, templatesPane, false);
|
|
||||||
// tabbedPane.setTabVisible(state, workflowPane, false);
|
|
||||||
// tabbedPane.setTabVisible(state, languagesPane, false);
|
|
||||||
// m_previewLink.setVisible(state, false);
|
|
||||||
// } else {
|
|
||||||
// tabbedPane.setTabVisible(state,
|
|
||||||
// templatesPane,
|
|
||||||
// !ContentSectionConfig.getConfig().getHideTemplatesTab());
|
|
||||||
// }
|
|
||||||
// Set the current tab based on parameters
|
|
||||||
if (setTab != null) {
|
|
||||||
Integer tab;
|
|
||||||
|
|
||||||
try {
|
|
||||||
tab = Integer.valueOf(setTab);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
// Stop processing set_tab parameter.
|
|
||||||
LOGGER.warn("Stopping processing of set_tab parameter.", ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab < tabbedPane.size()) {
|
|
||||||
tabbedPane.setSelectedIndex(state, tab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URL for displaying a certain item
|
|
||||||
*
|
|
||||||
* @param nodeURL The URL where this page is mounted
|
|
||||||
* @param itemId The id of the item to display
|
|
||||||
* @param tab The index of the tab to display
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getItemURL(final String nodeURL,
|
|
||||||
final Long itemId,
|
|
||||||
final int tab) {
|
|
||||||
return getItemURL(nodeURL, itemId, tab, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URL for displaying a certain item
|
|
||||||
*
|
|
||||||
* @param nodeURL The URL where this page is mounted
|
|
||||||
* @param itemId The id of the item to display
|
|
||||||
* @param tab The index of the tab to display
|
|
||||||
* @param streamlinedCreation Whether to activate Streamlined item authoring
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getItemURL(final String nodeURL,
|
|
||||||
final Long itemId,
|
|
||||||
final int tab,
|
|
||||||
final boolean streamlinedCreation) {
|
|
||||||
final StringBuilder urlBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
urlBuilder
|
|
||||||
.append(nodeURL)
|
|
||||||
.append(PageLocations.ITEM_PAGE)
|
|
||||||
.append("?")
|
|
||||||
.append(ITEM_ID)
|
|
||||||
.append("=")
|
|
||||||
.append(itemId.toString())
|
|
||||||
.append("&")
|
|
||||||
.append(SET_TAB)
|
|
||||||
.append("=")
|
|
||||||
.append(tab);
|
|
||||||
|
|
||||||
if (streamlinedCreation
|
|
||||||
&& CMSConfig.getConfig().isUseStreamlinedCreation()) {
|
|
||||||
|
|
||||||
urlBuilder
|
|
||||||
.append("&")
|
|
||||||
.append(STREAMLINED_CREATION)
|
|
||||||
.append("=")
|
|
||||||
.append(STREAMLINED_CREATION_ACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return urlBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param itemId
|
|
||||||
* @param tab
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @deprecated Use getItemURL instead
|
|
||||||
*/
|
|
||||||
public static String getRelativeItemURL(final Long itemId, final int tab) {
|
|
||||||
final StringBuilder url = new StringBuilder();
|
|
||||||
url
|
|
||||||
.append(PageLocations.ITEM_PAGE)
|
|
||||||
.append("?")
|
|
||||||
.append(ITEM_ID)
|
|
||||||
.append("=")
|
|
||||||
.append(itemId.toString())
|
|
||||||
.append("&")
|
|
||||||
.append(SET_TAB)
|
|
||||||
.append("=")
|
|
||||||
.append(tab);
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a URL for displaying a certain item.
|
|
||||||
*
|
|
||||||
* @param item the ContentItem object to display
|
|
||||||
* @param tab The index of the tab to display
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getItemURL(final ContentItem item,
|
|
||||||
final int tab) {
|
|
||||||
|
|
||||||
final ContentSection section = item.getContentType().getContentSection();
|
|
||||||
|
|
||||||
if (section == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
final String nodeURL = section.getPrimaryUrl() + "/";
|
|
||||||
|
|
||||||
return getItemURL(nodeURL, item.getObjectId(), tab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a URL for displaying a certain item.
|
|
||||||
*
|
|
||||||
* @param itemId the id of the ContentItem object to display
|
|
||||||
* @param tab The index of the tab to display
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getItemURL(final long itemId,
|
|
||||||
final int tab) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentItemRepository itemRepo = cdiUtil.findBean(
|
|
||||||
ContentItemRepository.class);
|
|
||||||
|
|
||||||
final Optional<ContentItem> item = itemRepo.findById(itemId);
|
|
||||||
|
|
||||||
if (item.isPresent()) {
|
|
||||||
return getItemURL(item.get(), tab);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect back to wherever the user came from, using the value of the
|
|
||||||
* return_url parameter.
|
|
||||||
*
|
|
||||||
* @param state The current page state
|
|
||||||
*/
|
|
||||||
public void redirectBack(final PageState state) {
|
|
||||||
try {
|
|
||||||
final String returnUrl = (String) state.getValue(returnUrlParameter);
|
|
||||||
state.getResponse().sendRedirect(returnUrl);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
LOGGER.error("IO Error redirecting back", ex);
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the preview URL.
|
|
||||||
*/
|
|
||||||
private String getPreviewURL(final PageState state) {
|
|
||||||
final ContentItem item = itemRequestLocal.getContentItem(state);
|
|
||||||
|
|
||||||
if (item instanceof CustomizedPreviewLink) {
|
|
||||||
final String previewLink = ((CustomizedPreviewLink) item).
|
|
||||||
getPreviewUrl(
|
|
||||||
state);
|
|
||||||
if ((previewLink == null) || previewLink.isEmpty()) {
|
|
||||||
return getDefaultPreviewLink(state, item);
|
|
||||||
} else {
|
|
||||||
return previewLink;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return getDefaultPreviewLink(state, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
* @param item
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getDefaultPreviewLink(final PageState state,
|
|
||||||
final ContentItem item) {
|
|
||||||
final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
// final ContentSectionManager sectionManager = cdiUtil.findBean(
|
|
||||||
// ContentSectionManager.class);
|
|
||||||
// final ItemResolver itemResolver = sectionManager
|
|
||||||
// .getItemResolver(section);
|
|
||||||
|
|
||||||
// Pass in the "Live" context since we need it for the preview
|
|
||||||
// return itemResolver.generateItemURL(state,
|
|
||||||
// item,
|
|
||||||
// section,
|
|
||||||
// CMSDispatcher.PREVIEW);
|
|
||||||
final ContentItemPageController controller = cdiUtil
|
|
||||||
.findBean(ContentItemPageController.class);
|
|
||||||
|
|
||||||
return controller.getDefaultPreviewLink(section, item, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final static GlobalizedMessage gz(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final static String lz(final String key) {
|
|
||||||
return (String) gz(key).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isStreamlinedCreationActive(final PageState state) {
|
|
||||||
return CMSConfig.getConfig().isUseStreamlinedCreation()
|
|
||||||
&& STREAMLINED_CREATION_ACTIVE.equals(state.getRequest().
|
|
||||||
getParameter(STREAMLINED_CREATION));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TabbedPane getTabbedPane() {
|
|
||||||
return tabbedPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected WizardSelector getWizardPane() {
|
|
||||||
return wizardPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the content type to the output.
|
|
||||||
*
|
|
||||||
* @param state PageState
|
|
||||||
* @param parent Parent document
|
|
||||||
*
|
|
||||||
* @return page
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Element generateXMLHelper(final PageState state,
|
|
||||||
final Document parent) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(itemRequestLocal.getContentItem(state),
|
|
||||||
"No ContentItem in current request.");
|
|
||||||
|
|
||||||
final Element page = super.generateXMLHelper(state, parent);
|
|
||||||
final Element contenttype = page.newChildElement("bebop:contentType",
|
|
||||||
BEBOP_XML_NS);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
|
|
||||||
final ContentItemPageController controller = cdiUtil
|
|
||||||
.findBean(ContentItemPageController.class);
|
|
||||||
contenttype
|
|
||||||
.setText(controller
|
|
||||||
.getContentTypeLabel(itemRequestLocal.getContentItem(state)));
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.cms.dispatcher.CMSDispatcher;
|
|
||||||
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentItemRepository;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
|
||||||
import org.librecms.contentsection.ContentSectionRepository;
|
|
||||||
import org.librecms.dispatcher.ItemResolver;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
class ContentItemPageController {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private GlobalizationHelper globalizationHelper;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContentSectionRepository sectionRepo;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContentSectionManager sectionManager;
|
|
||||||
@Inject
|
|
||||||
private ContentItemRepository itemRepo;
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected String getContentTypeLabel(final ContentItem item) {
|
|
||||||
|
|
||||||
final ContentItem theItem = itemRepo
|
|
||||||
.findById(item.getObjectId())
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String
|
|
||||||
.format("No ContentItem with ID %d in the database.",
|
|
||||||
item.getObjectId())));
|
|
||||||
|
|
||||||
return theItem
|
|
||||||
.getContentType()
|
|
||||||
.getLabel()
|
|
||||||
.getValue(globalizationHelper.getNegotiatedLocale());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected String getDefaultPreviewLink(final ContentSection section,
|
|
||||||
final ContentItem item,
|
|
||||||
final PageState state) {
|
|
||||||
|
|
||||||
final ContentSection contentSection = sectionRepo
|
|
||||||
.findById(section.getObjectId())
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String
|
|
||||||
.format("No ContentSectio with ID %d in the database.",
|
|
||||||
section.getObjectId())));
|
|
||||||
|
|
||||||
final ContentItem contentItem = itemRepo
|
|
||||||
.findById(item.getObjectId())
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String
|
|
||||||
.format("No ContentItem with ID %d in the database.",
|
|
||||||
item.getObjectId())));
|
|
||||||
|
|
||||||
final ItemResolver itemResolver = sectionManager
|
|
||||||
.getItemResolver(contentSection);
|
|
||||||
|
|
||||||
return itemResolver.generateItemURL(state,
|
|
||||||
contentItem,
|
|
||||||
contentSection,
|
|
||||||
CMSDispatcher.PREVIEW);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.PageLocations;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import com.arsdigita.web.ParameterMap;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The context bar of the content section UI.
|
|
||||||
*
|
|
||||||
* @author Justin Ross
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ContentSectionContextBar extends WorkspaceContextBar {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
ContentSectionContextBar.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Entry> entries(final PageState state) {
|
|
||||||
|
|
||||||
/* Include breadcrumb entries already set by content-center (i.e. the
|
|
||||||
* URL of the content center itself */
|
|
||||||
final List<Entry> entries = super.entries(state);
|
|
||||||
|
|
||||||
final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
final Stack<Entry> folderEntryStack = new Stack<>();
|
|
||||||
String currentFolderLabel = null;
|
|
||||||
ParameterMap params = new ParameterMap();
|
|
||||||
boolean isTemplate = false;
|
|
||||||
BigDecimal templateID = null;
|
|
||||||
|
|
||||||
if (CMS.getContext().hasContentItem()) {
|
|
||||||
final ContentItem item = CMS.getContext().getContentItem();
|
|
||||||
if (item == null) {
|
|
||||||
LOGGER.warn("item is null");
|
|
||||||
} else if (item.getContentType() == null) {
|
|
||||||
LOGGER.warn(
|
|
||||||
"item.getContentType() returns null. item.class.getName(): "
|
|
||||||
+ item.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
//ToDo NG - Not sure what happens here...
|
|
||||||
// final Optional<CcmObject> parent = item.getParent();
|
|
||||||
//
|
|
||||||
// while (!isTemplate
|
|
||||||
// && parent.isPresent()
|
|
||||||
// && parent.get() instanceof ContentItem) {
|
|
||||||
// if (currentFolderLabel != null) {
|
|
||||||
// final URL folderURL = URL.there
|
|
||||||
// (state.getRequest(),
|
|
||||||
// section.getPath() + "/" + PageLocations.SECTION_PAGE,
|
|
||||||
// params);
|
|
||||||
// folderEntryStack.push(new Entry(currentFolderLabel, folderURL));
|
|
||||||
// currentFolderLabel = null;
|
|
||||||
// params = new ParameterMap();
|
|
||||||
// }
|
|
||||||
// final ContentItem pitem = (ContentItem) parent;
|
|
||||||
//
|
|
||||||
// if (pitem instanceof Folder) {
|
|
||||||
// final Folder folder = (Folder) pitem;
|
|
||||||
// parent = folder.getParent();
|
|
||||||
//
|
|
||||||
// currentFolderLabel = folder.getLabel();
|
|
||||||
// if (parent != null || folder.equals(section.getRootFolder())) {
|
|
||||||
// params.setParameter
|
|
||||||
// (ContentSectionPage.SET_FOLDER, folder.getID());
|
|
||||||
// }
|
|
||||||
// } else if (pitem instanceof ContentBundle) {
|
|
||||||
// final ACSObject ppitem = pitem.getParent();
|
|
||||||
//
|
|
||||||
// if (ppitem != null && ppitem instanceof Folder) {
|
|
||||||
// final Folder folder = (Folder) ppitem;
|
|
||||||
//
|
|
||||||
// parent = folder.getParent();
|
|
||||||
// currentFolderLabel = folder.getLabel();
|
|
||||||
// if (parent != null || folder.equals(section
|
|
||||||
// .getRootFolder())) {
|
|
||||||
// params.setParameter
|
|
||||||
// (ContentSectionPage.SET_FOLDER, folder.getID());
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// parent = null;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// parent = null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTemplate) {
|
|
||||||
params.setParameter(ContentSectionPage.SET_TAB,
|
|
||||||
new BigDecimal(
|
|
||||||
ContentSectionPage.CONTENTTYPES_TAB));
|
|
||||||
params.setParameter(ContentSectionPage.SET_TEMPLATE, templateID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add section-level entry. if this is for an item page, the URL
|
|
||||||
// will be for the root folder.
|
|
||||||
final URL url = URL.there(
|
|
||||||
state.getRequest(),
|
|
||||||
String.format("%s/" + PageLocations.SECTION_PAGE,
|
|
||||||
section.getPrimaryUrl()),
|
|
||||||
params);
|
|
||||||
|
|
||||||
final String sectionTitle = lz("cms.ui.content_section");
|
|
||||||
final String title = sectionTitle + ": " + section.getLabel();
|
|
||||||
|
|
||||||
entries.add(new Entry(title, url));
|
|
||||||
|
|
||||||
// add any folders to the path now
|
|
||||||
while (!folderEntryStack.empty()) {
|
|
||||||
entries.add(folderEntryStack.pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String lz(final String key) {
|
|
||||||
return (String) ContentSectionPage.globalize(key).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,537 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.TabbedPane;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.PageLocations;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.dispatcher.CMSPage;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.cms.ui.category.CategoryAdminPane;
|
|
||||||
//ToDo NG import com.arsdigita.cms.ui.category.CategoryAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.role.RoleAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.type.ContentTypeAdminPane;
|
|
||||||
import com.arsdigita.cms.ui.workflow.WorkflowAdminPane;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.librecms.CMSConfig;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentItemVersion;
|
|
||||||
import org.librecms.contentsection.privileges.AdminPrivileges;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the entire admin UI for a content section.
|
|
||||||
*
|
|
||||||
* Developers Note: It is based on the dispatcher model is is going to be
|
|
||||||
* replaced by the newer servlet based model. @see
|
|
||||||
* c.ad.cms.ui.contentsection.MainPage (currently not active).
|
|
||||||
*
|
|
||||||
* @author Jack Chung
|
|
||||||
* @author Michael Pih
|
|
||||||
* @author Xixi D'Moon
|
|
||||||
* @author Justin Ross
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ContentSectionPage extends CMSPage implements ActionListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL parameter that can be passed in in order to set the current
|
|
||||||
* folder. This is used in getting back to the correct level of folder
|
|
||||||
* expansion from content item page.
|
|
||||||
*/
|
|
||||||
public static final String SET_FOLDER = "set_folder";
|
|
||||||
/**
|
|
||||||
* The URL parameter that can be passed in in order to set the current
|
|
||||||
* template (for setting the content type)
|
|
||||||
*/
|
|
||||||
public static final String SET_TEMPLATE = "set_template";
|
|
||||||
/**
|
|
||||||
* The URL parameter that can be passed in in order to set the current tab.
|
|
||||||
* This is a KLUDGE right now because the TabbedDialog's current tab is
|
|
||||||
* selected with a local state parameter.
|
|
||||||
*/
|
|
||||||
public static final String SET_TAB = "set_tab";
|
|
||||||
/**
|
|
||||||
* Index of the search tab
|
|
||||||
*/
|
|
||||||
public static final int SEARCH_TAB = 0;
|
|
||||||
/**
|
|
||||||
* Index of the browse tab
|
|
||||||
*/
|
|
||||||
public static final int BROWSE_TAB = 1;
|
|
||||||
/**
|
|
||||||
* Index of the roles tab
|
|
||||||
*/
|
|
||||||
public static final int ROLES_TAB = 2;
|
|
||||||
/**
|
|
||||||
* Index of the workflows tab
|
|
||||||
*/
|
|
||||||
public static final int WORKFLOW_TAB = 3;
|
|
||||||
/**
|
|
||||||
* Index of the lifecycles tab
|
|
||||||
*/
|
|
||||||
public static final int LIFECYCLES_TAB = 4;
|
|
||||||
/**
|
|
||||||
* Index of the categories tab
|
|
||||||
*/
|
|
||||||
public static final int CATEGORIES_TAB = 5;
|
|
||||||
/**
|
|
||||||
* Index of the content types tab
|
|
||||||
*/
|
|
||||||
public static final int CONTENTTYPES_TAB = 6;
|
|
||||||
public static final int USER_ADMIN_TAB = 7;
|
|
||||||
|
|
||||||
private TabbedPane m_tabbedPane;
|
|
||||||
private FolderAdminPane m_folderPane;
|
|
||||||
private BrowsePane m_browsePane;
|
|
||||||
private ItemSearch m_searchPane;
|
|
||||||
private AssetPane m_assetPane;
|
|
||||||
//ToDo NG private ImagesPane m_imagesPane;
|
|
||||||
private RoleAdminPane m_rolePane;
|
|
||||||
private WorkflowAdminPane m_workflowPane;
|
|
||||||
private LifecycleAdminPane m_lifecyclePane;
|
|
||||||
private CategoryAdminPane m_categoryPane;
|
|
||||||
private ContentTypeAdminPane m_typePane;
|
|
||||||
//private LayoutPanel m_userAdminPane;
|
|
||||||
private LayoutPanel m_csePane;
|
|
||||||
private ReportPane m_reportPane;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the content section index page containing - a Navigaton bar for
|
|
||||||
* the various tasks (items, search, images, ....) - a breadcrumb - ....
|
|
||||||
* Contains the UI for administering a content section.
|
|
||||||
*/
|
|
||||||
public ContentSectionPage() {
|
|
||||||
super(new Label(new TitlePrinter()), new SimpleContainer());
|
|
||||||
|
|
||||||
setClassAttr("cms-admin");
|
|
||||||
|
|
||||||
add(new GlobalNavigation());
|
|
||||||
add(new ContentSectionContextBar());
|
|
||||||
|
|
||||||
// Initialize the individual panes
|
|
||||||
m_folderPane = getFolderAdminPane();
|
|
||||||
m_browsePane = getBrowsePane();
|
|
||||||
m_searchPane = getSearchPane();
|
|
||||||
m_assetPane = getAssetPane();
|
|
||||||
//ToDo NG m_imagesPane = getImagesPane();
|
|
||||||
m_rolePane = getRoleAdminPane();
|
|
||||||
m_workflowPane = getWorkflowAdminPane();
|
|
||||||
m_lifecyclePane = getLifecycleAdminPane();
|
|
||||||
m_categoryPane = getCategoryAdminPane();
|
|
||||||
m_typePane = getContentTypeAdminPane();
|
|
||||||
// userAdminPane removed, used to contain just one item (reset user
|
|
||||||
// folder) which moved to the FolderAdminPane
|
|
||||||
//m_userAdminPane = getUserAdminPane();
|
|
||||||
m_csePane = getCSEPane();
|
|
||||||
m_reportPane = getReportPane();
|
|
||||||
|
|
||||||
// The panes
|
|
||||||
m_tabbedPane = createTabbedPane();
|
|
||||||
m_tabbedPane.setIdAttr("page-body");
|
|
||||||
m_tabbedPane.addActionListener(this);
|
|
||||||
add(m_tabbedPane);
|
|
||||||
|
|
||||||
addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void actionPerformed(ActionEvent e) {
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
final String tab = state.getRequest().getParameter(SET_TAB);
|
|
||||||
|
|
||||||
if (tab != null) {
|
|
||||||
m_tabbedPane.setSelectedIndex(state, Integer.valueOf(tab)
|
|
||||||
.intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
final PermissionChecker permissionChecker = CdiUtil
|
|
||||||
.createCdiUtil().findBean(PermissionChecker.class);
|
|
||||||
|
|
||||||
if (CMSConfig.getConfig().isHideAdminTabs()) {
|
|
||||||
m_tabbedPane.setTabVisible(
|
|
||||||
state,
|
|
||||||
m_workflowPane,
|
|
||||||
permissionChecker.isPermitted(AdminPrivileges.ADMINISTER_WORKFLOWS));
|
|
||||||
m_tabbedPane.setTabVisible(
|
|
||||||
state,
|
|
||||||
m_categoryPane,
|
|
||||||
permissionChecker.isPermitted(
|
|
||||||
AdminPrivileges.ADMINISTER_CATEGORIES));
|
|
||||||
m_tabbedPane.setTabVisible(
|
|
||||||
state,
|
|
||||||
m_lifecyclePane,
|
|
||||||
permissionChecker.isPermitted(
|
|
||||||
AdminPrivileges.ADMINISTER_LIFECYLES));
|
|
||||||
m_tabbedPane.setTabVisible(
|
|
||||||
state,
|
|
||||||
m_typePane,
|
|
||||||
permissionChecker.isPermitted(
|
|
||||||
AdminPrivileges.ADMINISTER_CONTENT_TYPES));
|
|
||||||
|
|
||||||
m_tabbedPane.setTabVisible(
|
|
||||||
state,
|
|
||||||
m_rolePane,
|
|
||||||
permissionChecker.isPermitted(
|
|
||||||
AdminPrivileges.ADMINISTER_ROLES));
|
|
||||||
// csePane: should check permission
|
|
||||||
m_tabbedPane.setTabVisible(state, m_csePane, true);
|
|
||||||
// TODO Check for reportPane as well
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the browse pane. Overriding this method to
|
|
||||||
* return null will prevent this tab from appearing.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected FolderAdminPane getFolderAdminPane() {
|
|
||||||
if (m_folderPane == null) {
|
|
||||||
m_folderPane = new FolderAdminPane();
|
|
||||||
}
|
|
||||||
return m_folderPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the browse pane. Overriding this method to
|
|
||||||
* return null will prevent this tab from appearing.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected BrowsePane getBrowsePane() {
|
|
||||||
if (m_browsePane == null) {
|
|
||||||
m_browsePane = new BrowsePane();
|
|
||||||
}
|
|
||||||
return m_browsePane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the search pane. Overriding this method to
|
|
||||||
* return null will prevent this tab from appearing.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected ItemSearch getSearchPane() {
|
|
||||||
if (m_searchPane == null) {
|
|
||||||
m_searchPane
|
|
||||||
= new ItemSearch(
|
|
||||||
ContentItemVersion.DRAFT.toString(),
|
|
||||||
CMSConfig.getConfig().isLimitItemSearchToContentSection());
|
|
||||||
}
|
|
||||||
return m_searchPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AssetPane getAssetPane() {
|
|
||||||
if (m_assetPane == null) {
|
|
||||||
m_assetPane = new AssetPane();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_assetPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo NG
|
|
||||||
// protected ImagesPane getImagesPane() {
|
|
||||||
// if (m_imagesPane == null) {
|
|
||||||
// m_imagesPane = new ImagesPane();
|
|
||||||
// }
|
|
||||||
// return m_imagesPane;
|
|
||||||
// }
|
|
||||||
protected RoleAdminPane getRoleAdminPane() {
|
|
||||||
if (m_rolePane == null) {
|
|
||||||
m_rolePane = new RoleAdminPane();
|
|
||||||
}
|
|
||||||
return m_rolePane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the workflow administration pane. Overriding
|
|
||||||
* this method to return null will prevent this tab from appearing.
|
|
||||||
*/
|
|
||||||
protected WorkflowAdminPane getWorkflowAdminPane() {
|
|
||||||
if (m_workflowPane == null) {
|
|
||||||
m_workflowPane = new WorkflowAdminPane();
|
|
||||||
}
|
|
||||||
return m_workflowPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the lifecycle administration pane. Overriding
|
|
||||||
* this method to return null will prevent this tab from appearing.
|
|
||||||
*/
|
|
||||||
protected LifecycleAdminPane getLifecycleAdminPane() {
|
|
||||||
if (m_lifecyclePane == null) {
|
|
||||||
m_lifecyclePane = new LifecycleAdminPane();
|
|
||||||
}
|
|
||||||
return m_lifecyclePane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the category administration pane. Overriding
|
|
||||||
* this method to return null will prevent this tab from appearing.
|
|
||||||
*/
|
|
||||||
protected CategoryAdminPane getCategoryAdminPane() {
|
|
||||||
if (m_categoryPane == null) {
|
|
||||||
m_categoryPane = new CategoryAdminPane();
|
|
||||||
}
|
|
||||||
return m_categoryPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates, and then caches, the content type administration pane.
|
|
||||||
* Overriding this method to return null will prevent this tab from
|
|
||||||
* appearing.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected ContentTypeAdminPane getContentTypeAdminPane() {
|
|
||||||
if (m_typePane == null) {
|
|
||||||
m_typePane = new ContentTypeAdminPane();
|
|
||||||
}
|
|
||||||
return m_typePane;
|
|
||||||
}
|
|
||||||
|
|
||||||
// protected LayoutPanel getUserAdminPane() {
|
|
||||||
// if (m_userAdminPane == null) {
|
|
||||||
// m_userAdminPane = new LayoutPanel();
|
|
||||||
// m_userAdminPane.setLeft(new SimpleComponent());
|
|
||||||
// m_userAdminPane.setBody(new UserAdminPane());
|
|
||||||
// }
|
|
||||||
// return m_userAdminPane;
|
|
||||||
// }
|
|
||||||
protected LayoutPanel getCSEPane() {
|
|
||||||
if (m_csePane == null) {
|
|
||||||
m_csePane = new LayoutPanel();
|
|
||||||
m_csePane.setLeft(new SimpleComponent());
|
|
||||||
m_csePane.setBody(new ContentSoonExpiredPane());
|
|
||||||
}
|
|
||||||
return m_csePane;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ReportPane getReportPane() {
|
|
||||||
if (m_reportPane == null) {
|
|
||||||
m_reportPane = new ReportPane();
|
|
||||||
}
|
|
||||||
return m_reportPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified component, with the specified tab name, to the tabbed
|
|
||||||
* pane only if it is not null.
|
|
||||||
*
|
|
||||||
* @param pane The pane to which to add the tab
|
|
||||||
* @param tabName The name of the tab if it's added
|
|
||||||
* @param comp The component to add to the pane
|
|
||||||
*/
|
|
||||||
protected void addToPane(final TabbedPane pane,
|
|
||||||
final String tabName,
|
|
||||||
final Component comp) {
|
|
||||||
if (comp != null) {
|
|
||||||
pane.addTab(new Label(tabName), comp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tab(final TabbedPane pane,
|
|
||||||
final String key,
|
|
||||||
final Component tab) {
|
|
||||||
if (tab != null) {
|
|
||||||
pane.addTab(new Label(gz(key)), tab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Created the TabbedPane to use for this page. Adds the tabs to the pane.
|
|
||||||
* The default implementation uses a {@link
|
|
||||||
* com.arsdigita.bebop.TabbedPane}. This implementation also adds browse,
|
|
||||||
* search, staff admin, viewers admin, workflow admin, category admin, and
|
|
||||||
* content type panes.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Developers can override this method to add only the tabs they want, or to
|
|
||||||
* add additional tabs after the default CMS tabs are added.</p>
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected TabbedPane createTabbedPane() {
|
|
||||||
final TabbedPane pane = new TabbedPane();
|
|
||||||
|
|
||||||
//tab(pane, "cms.ui.folders", getFolderAdminPane());
|
|
||||||
tab(pane, "cms.ui.browse", getBrowsePane());
|
|
||||||
tab(pane, "cms.ui.search", getSearchPane());
|
|
||||||
tab(pane, "cms.ui.assets", getAssetPane());
|
|
||||||
// ToDo NG replace with media tab tab(pane, "cms.ui.images", getImagesPane());
|
|
||||||
tab(pane, "cms.ui.roles", getRoleAdminPane());
|
|
||||||
tab(pane, "cms.ui.workflows", getWorkflowAdminPane());
|
|
||||||
tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane());
|
|
||||||
tab(pane, "cms.ui.categories", getCategoryAdminPane());
|
|
||||||
tab(pane, "cms.ui.content_types", getContentTypeAdminPane());
|
|
||||||
tab(pane, "cms.ui.cse", getCSEPane());
|
|
||||||
tab(pane, "cms.ui.reports", getReportPane());
|
|
||||||
|
|
||||||
return pane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the request-local content section.
|
|
||||||
*
|
|
||||||
* @param request The HTTP request
|
|
||||||
*
|
|
||||||
* @return The current content section
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ContentSection getContentSection(final HttpServletRequest request) {
|
|
||||||
// Resets all content sections associations.
|
|
||||||
ContentSection section = super.getContentSection(request);
|
|
||||||
Assert.exists(section);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When a new tab is selected, reset the state of the formerly-selected
|
|
||||||
* pane.
|
|
||||||
*
|
|
||||||
* @param event The event fired by selecting a tab
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Component pane = m_tabbedPane.getCurrentPane(state);
|
|
||||||
|
|
||||||
//ToDo NG if (pane == m_searchPane) {
|
|
||||||
// m_searchPane.reset(state);
|
|
||||||
// } else if (pane == m_imagesPane) {
|
|
||||||
// m_imagesPane.reset(state);
|
|
||||||
// } else
|
|
||||||
if (pane == m_assetPane) {
|
|
||||||
m_assetPane.reset(state);
|
|
||||||
} else if (pane == m_folderPane) {
|
|
||||||
m_folderPane.reset(state);
|
|
||||||
//ToDo NG } else if (pane == m_browsePane) {
|
|
||||||
// m_browsePane.reset(state);
|
|
||||||
// } else if (pane == m_rolePane) {
|
|
||||||
// m_rolePane.reset(state);
|
|
||||||
} else if (pane == m_workflowPane) {
|
|
||||||
m_workflowPane.reset(state);
|
|
||||||
} else if (pane == m_lifecyclePane) {
|
|
||||||
m_lifecyclePane.reset(state);
|
|
||||||
} else if (pane == m_categoryPane) {
|
|
||||||
m_categoryPane.reset(state);
|
|
||||||
} else if (pane == m_typePane) {
|
|
||||||
m_typePane.reset(state);
|
|
||||||
// } else if (pane == m_userAdminPane) {
|
|
||||||
//m_userAdminPane.reset(state);
|
|
||||||
} else if (pane == m_csePane) {
|
|
||||||
m_csePane.reset(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a URL for displaying the tab
|
|
||||||
*
|
|
||||||
* @param item The item from which we get the corresponding content section
|
|
||||||
* @param tab The index of the tab to display
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getSectionURL(final ContentItem item, final int tab) {
|
|
||||||
// Get the content section associated with the content item.
|
|
||||||
final ContentSection section = item.getContentType().getContentSection();
|
|
||||||
|
|
||||||
final String url = section.getPrimaryUrl() + PageLocations.SECTION_PAGE
|
|
||||||
+ "?" + SET_TAB + "=" + tab;
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GlobalizedMessage gz(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getting the GlobalizedMessage using a CMS Class targetBundle.
|
|
||||||
*
|
|
||||||
* @param key The resource key
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @pre key != null
|
|
||||||
*/
|
|
||||||
public static GlobalizedMessage globalize(final String key) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @param args
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static GlobalizedMessage globalize(final String key,
|
|
||||||
final Object[] args) {
|
|
||||||
return new GlobalizedMessage(key, CmsConstants.CMS_BUNDLE, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to be able to use a PrintListener to set the titel of the
|
|
||||||
* page.
|
|
||||||
*/
|
|
||||||
private static class TitlePrinter implements PrintListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final Label l = (Label) event.getTarget();
|
|
||||||
|
|
||||||
l.setLabel(CMS.getContext().getContentSection().getLabel());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class ContentSectionRequestLocal extends RequestLocal {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object initialValue(final PageState state) {
|
|
||||||
return CMS.getContext().getContentSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ContentSection getContentSection(final PageState state) {
|
|
||||||
return (ContentSection) get(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,488 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormSection;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.FileUpload;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.OptionGroup;
|
|
||||||
import com.arsdigita.bebop.form.SingleSelect;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.dispatcher.MultipartHttpServletRequest;
|
|
||||||
import java.io.File;
|
|
||||||
import javax.activation.MimeType;
|
|
||||||
import javax.activation.MimeTypeParseException;
|
|
||||||
import javax.activation.MimetypesFileTypeMap;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A form section with two widgets: a mime-type selection widget and a file
|
|
||||||
* upload widget. The section will attempt to automatically guess the mime type
|
|
||||||
* from the filename (if necessary), and return the mime type.
|
|
||||||
*
|
|
||||||
* @author Stanislav Freidin (sfreidin@arsdigita.com)
|
|
||||||
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class FileUploadSection extends FormSection {
|
|
||||||
|
|
||||||
private SingleSelect mimeWidget;
|
|
||||||
private FileUpload fileWidget;
|
|
||||||
private String mimePrefix;
|
|
||||||
private String defaultMimeType;
|
|
||||||
private String parameterPrefix;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The mime type widget
|
|
||||||
*/
|
|
||||||
public static final String MIME_TYPE = "mime_type";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The file upload widget
|
|
||||||
*/
|
|
||||||
public static final String FILE_UPLOAD = "file_upload";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Automatically guess the mime type
|
|
||||||
*/
|
|
||||||
public static final String GUESS_MIME = "-guess-";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param panel The panel that is to be used to lay out the components
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final GlobalizedMessage mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final Container panel) {
|
|
||||||
this(mimeLabel, mimePrefix, defaultMimeType, "", panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param panel The panel that is to be used to lay out the components
|
|
||||||
*
|
|
||||||
* @deprecated use the same constructor but with the GlobalizedMessage for
|
|
||||||
* the mimeLabel
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final String mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final Container panel) {
|
|
||||||
// This takes advantage of the fact that the "key" is returned
|
|
||||||
// when it is not present in the message bundle
|
|
||||||
this(new GlobalizedMessage(mimeLabel),
|
|
||||||
mimePrefix,
|
|
||||||
defaultMimeType,
|
|
||||||
panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
|
|
||||||
* parameter names so that more than 1 file upload widgets may be used per
|
|
||||||
* form
|
|
||||||
*
|
|
||||||
* @param panel The panel that is to be used to lay out the components
|
|
||||||
*
|
|
||||||
* @deprecated use the same constructor but with the GlobalizedMessage for
|
|
||||||
* the mimeLabel
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final String mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final String parameterPrefix,
|
|
||||||
final Container panel
|
|
||||||
) {
|
|
||||||
// This takes advantage of the fact that the "key" is returned
|
|
||||||
// when it is not present in the message bundle
|
|
||||||
this(new GlobalizedMessage(mimeLabel, CmsConstants.CMS_BUNDLE),
|
|
||||||
mimePrefix,
|
|
||||||
defaultMimeType,
|
|
||||||
parameterPrefix,
|
|
||||||
panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
|
|
||||||
* parameter names so that more than 1 file upload widgets may be used per
|
|
||||||
* form
|
|
||||||
*
|
|
||||||
* @param panel The panel that is to be used to lay out the components
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final GlobalizedMessage mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final String parameterPrefix,
|
|
||||||
final Container panel) {
|
|
||||||
|
|
||||||
super(panel);
|
|
||||||
|
|
||||||
this.mimePrefix = mimePrefix;
|
|
||||||
this.defaultMimeType = defaultMimeType;
|
|
||||||
if (parameterPrefix == null) {
|
|
||||||
this.parameterPrefix = "";
|
|
||||||
} else {
|
|
||||||
this.parameterPrefix = parameterPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
add(new Label(mimeLabel, false));
|
|
||||||
mimeWidget = new SingleSelect(getMimeTypeWidgetName());
|
|
||||||
addMimeOptions(mimeWidget, mimePrefix);
|
|
||||||
mimeWidget
|
|
||||||
.addOption(new Option(GUESS_MIME,
|
|
||||||
new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.file_upload.auto_detect",
|
|
||||||
CmsConstants.CMS_BUNDLE))));
|
|
||||||
|
|
||||||
mimeWidget.setDefaultValue(GUESS_MIME);
|
|
||||||
add(mimeWidget);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage("cms.ui.upload_new_content",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
fileWidget = new FileUpload(getFileUploadWidgetName());
|
|
||||||
add(fileWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
|
|
||||||
* parameter names so that more than 1 file upload widgets may be used per
|
|
||||||
* form
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final GlobalizedMessage mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final String parameterPrefix) {
|
|
||||||
this(mimeLabel,
|
|
||||||
mimePrefix,
|
|
||||||
defaultMimeType,
|
|
||||||
parameterPrefix,
|
|
||||||
new ColumnPanel(2, true));
|
|
||||||
final ColumnPanel panel = (ColumnPanel) getPanel();
|
|
||||||
panel.setBorder(false);
|
|
||||||
panel.setPadColor("#FFFFFF");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @param parameterPrefix Prepended to MIME_TYPE and FILE_UPLOAD for
|
|
||||||
* parameter names so that more than 1 file upload widgets may be used per
|
|
||||||
* form
|
|
||||||
*
|
|
||||||
* @deprecated use the same constructor but with the GlobalizedMessage for
|
|
||||||
* the mimeLabel
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final String mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType,
|
|
||||||
final String parameterPrefix) {
|
|
||||||
// This takes advantage of the fact that the "key" is returned
|
|
||||||
// when it is not present in the message bundle
|
|
||||||
this(new GlobalizedMessage(mimeLabel, CmsConstants.CMS_BUNDLE),
|
|
||||||
mimePrefix,
|
|
||||||
defaultMimeType,
|
|
||||||
parameterPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The label for the mime type widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
* @deprecated use the same constructor but with the GlobalizedMessage for
|
|
||||||
* the mimeLabel
|
|
||||||
*/
|
|
||||||
public FileUploadSection(final String mimeLabel,
|
|
||||||
final String mimePrefix,
|
|
||||||
final String defaultMimeType) {
|
|
||||||
|
|
||||||
// This takes advantage of the fact that the "key" is returned
|
|
||||||
// when it is not present in the message bundle
|
|
||||||
this(new GlobalizedMessage(mimeLabel, CmsConstants.CMS_BUNDLE),
|
|
||||||
mimePrefix,
|
|
||||||
defaultMimeType,
|
|
||||||
"");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new FileUploadSection
|
|
||||||
*
|
|
||||||
* @param mimeLabel The GlobalizedMessage for the label for the mime type
|
|
||||||
* widget
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
* @param defaultMimeType The default mime type that should be assumed if
|
|
||||||
* the guessing fails
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public FileUploadSection(GlobalizedMessage mimeLabel,
|
|
||||||
String mimePrefix,
|
|
||||||
String defaultMimeType) {
|
|
||||||
this(mimeLabel, mimePrefix, defaultMimeType, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to guess the mime type from the filename, and return it. The parent
|
|
||||||
* form should call this method in its process listener. Note that this
|
|
||||||
* method may return null if the mime type could not be guessed.
|
|
||||||
*
|
|
||||||
* @param event The form section event
|
|
||||||
* @return The mime type of the file.
|
|
||||||
*/
|
|
||||||
public MimeType getMimeType(final FormSectionEvent event) {
|
|
||||||
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
|
|
||||||
final String fileName = (String) data.get(getFileUploadWidgetName());
|
|
||||||
final String mimeTypeName = (String) data.get(getMimeTypeWidgetName());
|
|
||||||
|
|
||||||
// Guess the mime type from the filename
|
|
||||||
MimeType mimeType = null;
|
|
||||||
if (fileName != null) {
|
|
||||||
try {
|
|
||||||
if (GUESS_MIME.equals(mimeTypeName)) {
|
|
||||||
// Guess the mime type from the file extension
|
|
||||||
mimeType = new MimeType(MimetypesFileTypeMap
|
|
||||||
.getDefaultFileTypeMap()
|
|
||||||
.getContentType(fileName));
|
|
||||||
} else {
|
|
||||||
mimeType = new MimeType(mimeTypeName);
|
|
||||||
}
|
|
||||||
} catch (MimeTypeParseException ex) {
|
|
||||||
mimeType = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failed to guess it, failed to load it, fall back on the default
|
|
||||||
if (mimeType == null) {
|
|
||||||
try {
|
|
||||||
mimeType = new MimeType(defaultMimeType);
|
|
||||||
} catch (MimeTypeParseException ex) {
|
|
||||||
mimeType = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a File object from the file upload widget. The containing form
|
|
||||||
* should call this method in its process listener.
|
|
||||||
*
|
|
||||||
* @param event The form section event
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public File getFile(final FormSectionEvent event) {
|
|
||||||
|
|
||||||
final String fileName = getFileName(event);
|
|
||||||
|
|
||||||
if (fileName != null && fileName.length() > 0) {
|
|
||||||
return ((MultipartHttpServletRequest) unwrapRequest(event
|
|
||||||
.getPageState()
|
|
||||||
.getRequest()))
|
|
||||||
.getFile(getFileUploadWidgetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServletRequest unwrapRequest(final HttpServletRequest request) {
|
|
||||||
|
|
||||||
ServletRequest current = request;
|
|
||||||
while (current instanceof HttpServletRequestWrapper) {
|
|
||||||
current = ((HttpServletRequestWrapper) current).getRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a filename from the file upload widget. The containing form should
|
|
||||||
* call this method in its process listener.
|
|
||||||
*
|
|
||||||
* @param event The form section event
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getFileName(final FormSectionEvent event) {
|
|
||||||
|
|
||||||
return event
|
|
||||||
.getFormData()
|
|
||||||
.getString(getFileUploadWidgetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value for the mime type widget. The containing form should call
|
|
||||||
* this method in its init listener
|
|
||||||
*
|
|
||||||
* @param event The form section event
|
|
||||||
* @param mimeType The mime type to set, such as "text/html" or "img/jpeg"
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void setMimeType(final FormSectionEvent event,
|
|
||||||
final String mimeType) {
|
|
||||||
event
|
|
||||||
.getFormData()
|
|
||||||
.put(getMimeTypeWidgetName(), mimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the mime type widget
|
|
||||||
*/
|
|
||||||
public SingleSelect getMimeTypeWidget() {
|
|
||||||
return mimeWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the file upload widget
|
|
||||||
*/
|
|
||||||
public FileUpload getFileUploadWidget() {
|
|
||||||
return fileWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the parameter name prefix
|
|
||||||
*/
|
|
||||||
public String getParameterPrefix() {
|
|
||||||
return parameterPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the file upload parameter name
|
|
||||||
*/
|
|
||||||
public String getFileUploadWidgetName() {
|
|
||||||
return parameterPrefix + FILE_UPLOAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the mime typeparameter name
|
|
||||||
*/
|
|
||||||
public String getMimeTypeWidgetName() {
|
|
||||||
return parameterPrefix + MIME_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add mime-type options to the option group by loading all mime types which
|
|
||||||
* match a certain prefix from the database
|
|
||||||
*
|
|
||||||
* @param mimeTypeOptions The mime type widget to which options should be
|
|
||||||
* added
|
|
||||||
*
|
|
||||||
* @param mimePrefix Populate the mime type widget with all mime types that
|
|
||||||
* match the prefix. Some of the possible prefixes are "text", "image",
|
|
||||||
* "binary", etc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static void addMimeOptions(final OptionGroup mimeTypeOptions,
|
|
||||||
final String mimePrefix) {
|
|
||||||
|
|
||||||
// MimeTypeCollection types;
|
|
||||||
// if (mimePrefix == null || mimePrefix.equals("")) {
|
|
||||||
// types = MimeType.getAllMimeTypes();
|
|
||||||
// } else {
|
|
||||||
// types = MimeType.searchMimeTypes(mimePrefix + "/");
|
|
||||||
// }
|
|
||||||
// while (types.next()) {
|
|
||||||
// MimeType type = types.getMimeType();
|
|
||||||
// mimeTypeOptions.addOption(new Option(type.getMimeType(), type.getLabel()));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,468 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ActionLink;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.SegmentedPanel;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.event.ActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.ActionListener;
|
|
||||||
import com.arsdigita.bebop.event.ChangeEvent;
|
|
||||||
import com.arsdigita.bebop.event.ChangeListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.parameters.LongParameter;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.authoring.CreationSelector;
|
|
||||||
import com.arsdigita.cms.ui.authoring.news.NewItemForm;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderCreateForm;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderEditorForm;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderManipulator;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderPath;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderRequestLocal;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
|
|
||||||
import com.arsdigita.cms.ui.permissions.CMSPermissionsPane;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import com.arsdigita.toolbox.ui.ActionGroup;
|
|
||||||
import com.arsdigita.ui.CcmObjectSelectionModel;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.security.PermissionManager;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates a {@link FolderManipulator} in order to create a flat item
|
|
||||||
* listing. Also contains a new item form.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:sfreidin@arsdigita.com">Stanislav Freidin</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class FlatItemList extends SegmentedPanel implements FormProcessListener,
|
|
||||||
ChangeListener,
|
|
||||||
FormSubmissionListener,
|
|
||||||
Resettable,
|
|
||||||
ActionListener {
|
|
||||||
|
|
||||||
private static final String CONTENT_TYPE_ID = "ct";
|
|
||||||
// The folder selectors
|
|
||||||
private final FolderSelectionModel folderSelectionModel;
|
|
||||||
private final FolderRequestLocal folderRequestLocal;
|
|
||||||
private final NewItemForm newItemForm;
|
|
||||||
private final SingleSelectionModel<Long> typeSelectionModel;
|
|
||||||
private final CreationSelector creationSelector;
|
|
||||||
private final FolderManipulator folderManipulator;
|
|
||||||
private final FolderCreateForm folderCreator;
|
|
||||||
// private final ActionLink m_setHomeFolderAction;
|
|
||||||
// private final ActionLink m_removeHomeFolderAction;
|
|
||||||
private final ActionLink createFolderAction;
|
|
||||||
// private final ActionLink togglePrivateAction;
|
|
||||||
// private final Label m_homeFolderLabel;
|
|
||||||
private final Segment browseSegment;
|
|
||||||
private final Segment newItemSegment;
|
|
||||||
private final Segment newFolderSegment;
|
|
||||||
private final Segment editFolderSegment;
|
|
||||||
private final Segment permissionsSegment;
|
|
||||||
private final CMSPermissionsPane permissionsPane;
|
|
||||||
// Folder edit/rename functionality.
|
|
||||||
private final ActionLink editFolderAction;
|
|
||||||
private final FolderEditorForm folderEditor;
|
|
||||||
private final Label contentLabel;
|
|
||||||
private final FolderPath folderPath;
|
|
||||||
private final Label chooseLabel;
|
|
||||||
private final StringParameter selectedLanguageParam;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new item listing pane. The provided folder selection model is
|
|
||||||
* used to keep track of the currently displayed folder.
|
|
||||||
*
|
|
||||||
* @param folderRequestLocal
|
|
||||||
* @param folderSelectionModel maintains the currently displayed folder.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public FlatItemList(final FolderRequestLocal folderRequestLocal,
|
|
||||||
final FolderSelectionModel folderSelectionModel) {
|
|
||||||
this.folderRequestLocal = folderRequestLocal;
|
|
||||||
this.folderSelectionModel = folderSelectionModel;
|
|
||||||
folderSelectionModel.addChangeListener(event -> reset(event
|
|
||||||
.getPageState()));
|
|
||||||
|
|
||||||
setIdAttr("flat-item-list");
|
|
||||||
|
|
||||||
newItemSegment = addSegment();
|
|
||||||
newItemSegment.setIdAttr("folder-new-item");
|
|
||||||
|
|
||||||
newFolderSegment = addSegment();
|
|
||||||
newFolderSegment.setIdAttr("folder-new-folder");
|
|
||||||
|
|
||||||
editFolderSegment = addSegment();
|
|
||||||
editFolderSegment.setIdAttr("folder-edit-folder");
|
|
||||||
|
|
||||||
browseSegment = addSegment();
|
|
||||||
browseSegment.setIdAttr("folder-browse");
|
|
||||||
|
|
||||||
final ActionGroup browseActions = new ActionGroup();
|
|
||||||
browseSegment.add(browseActions);
|
|
||||||
|
|
||||||
// The top 'browse' segment
|
|
||||||
contentLabel = new Label(globalize("cms.ui.contents_of"), false);
|
|
||||||
browseSegment.addHeader(contentLabel);
|
|
||||||
chooseLabel = new Label(globalize("cms.ui.choose_target_folder"),
|
|
||||||
false);
|
|
||||||
browseSegment.addHeader(chooseLabel);
|
|
||||||
folderPath = new FolderPath(folderSelectionModel);
|
|
||||||
|
|
||||||
browseSegment.addHeader(folderPath);
|
|
||||||
folderManipulator = new FolderManipulator(folderSelectionModel);
|
|
||||||
folderManipulator.getItemView().addProcessListener(this);
|
|
||||||
folderManipulator.getTargetSelector().addProcessListener(this);
|
|
||||||
folderManipulator.getTargetSelector().addSubmissionListener(this);
|
|
||||||
|
|
||||||
browseActions.setSubject(folderManipulator);
|
|
||||||
|
|
||||||
createFolderAction = new ActionLink(new Label(globalize(
|
|
||||||
"cms.ui.new_folder")));
|
|
||||||
createFolderAction.addActionListener(this);
|
|
||||||
browseActions.addAction(createFolderAction);
|
|
||||||
|
|
||||||
editFolderAction = new ActionLink(new Label(globalize(
|
|
||||||
"cms.ui.edit_folder")));
|
|
||||||
editFolderAction.addActionListener(this);
|
|
||||||
browseActions.addAction(editFolderAction);
|
|
||||||
|
|
||||||
newItemForm = new SectionNewItemForm("newItem");
|
|
||||||
newItemForm.addProcessListener(this);
|
|
||||||
browseActions.addAction(newItemForm);
|
|
||||||
|
|
||||||
permissionsSegment = addSegment();
|
|
||||||
permissionsSegment.setIdAttr("folder-permissions");
|
|
||||||
|
|
||||||
final ActionGroup permissionActions = new ActionGroup();
|
|
||||||
permissionsSegment.add(permissionActions);
|
|
||||||
|
|
||||||
permissionsSegment.addHeader(new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.permissions", CmsConstants.CMS_BUNDLE)));
|
|
||||||
|
|
||||||
selectedLanguageParam = new StringParameter(ContentItemPage.SELECTED_LANGUAGE);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionManager permissionManager = cdiUtil.findBean(
|
|
||||||
PermissionManager.class);
|
|
||||||
final List<String> privileges = permissionManager
|
|
||||||
.listDefiniedPrivileges(ItemPrivileges.class);
|
|
||||||
final Map<String, String> privNameMap = new HashMap<>();
|
|
||||||
privileges.forEach(privilege -> privNameMap.put(privilege, privilege));
|
|
||||||
|
|
||||||
permissionsPane = new CMSPermissionsPane(
|
|
||||||
privileges.toArray(new String[]{}),
|
|
||||||
privNameMap,
|
|
||||||
(CcmObjectSelectionModel) folderSelectionModel);
|
|
||||||
permissionActions.setSubject(permissionsPane);
|
|
||||||
|
|
||||||
newItemSegment.addHeader(new Label(globalize("cms.ui.new_item")));
|
|
||||||
typeSelectionModel = new ParameterSingleSelectionModel<>(
|
|
||||||
new LongParameter(CONTENT_TYPE_ID));
|
|
||||||
typeSelectionModel.addChangeListener(this);
|
|
||||||
|
|
||||||
creationSelector = new CreationSelector(typeSelectionModel,
|
|
||||||
folderSelectionModel,
|
|
||||||
selectedLanguageParam);
|
|
||||||
newItemSegment.add(creationSelector);
|
|
||||||
//m_newItemSeg.add(new Label("<br/>", false));
|
|
||||||
|
|
||||||
// The 'new folder' segment
|
|
||||||
newFolderSegment.addHeader(new Label(globalize("cms.ui.new_folder")));
|
|
||||||
// final Form folderCreate = new Form("fcreat");
|
|
||||||
folderCreator = new FolderCreateForm("fcreat", folderSelectionModel);
|
|
||||||
folderCreator.addSubmissionListener(this);
|
|
||||||
folderCreator.addProcessListener(this);
|
|
||||||
//folderCreator.add(folderCreator);
|
|
||||||
newFolderSegment.add(folderCreator);
|
|
||||||
newFolderSegment.add(new Label("<br/>", false));
|
|
||||||
|
|
||||||
editFolderSegment.addHeader(new Label(globalize("cms.ui.edit_folder")));
|
|
||||||
folderEditor = new FolderEditorForm("fedit", folderSelectionModel);
|
|
||||||
folderEditor.addSubmissionListener(this);
|
|
||||||
folderEditor.addProcessListener(this);
|
|
||||||
//Form folderEditorForm = new Form("fedit_form");
|
|
||||||
//folderEditorForm.add(folderEditor);
|
|
||||||
editFolderSegment.add(folderEditor);
|
|
||||||
editFolderSegment.add(new Label("<br/>", false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.setVisibleDefault(chooseLabel, false);
|
|
||||||
// page.setVisibleDefault(browseSegment, true);
|
|
||||||
page.setVisibleDefault(newItemSegment, false);
|
|
||||||
page.setVisibleDefault(newFolderSegment, false);
|
|
||||||
page.setVisibleDefault(editFolderSegment, false);
|
|
||||||
|
|
||||||
page.addComponentStateParam(this,
|
|
||||||
typeSelectionModel.getStateParameter());
|
|
||||||
page.addGlobalStateParam(selectedLanguageParam);
|
|
||||||
|
|
||||||
page.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (state.isVisibleOnPage(FlatItemList.this)) {
|
|
||||||
showHideSegments(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show/hide segments based on access checks.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @pre ( state != null )
|
|
||||||
*/
|
|
||||||
private void showHideSegments(final PageState state) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
final Folder folder = folderRequestLocal.getFolder(state);
|
|
||||||
|
|
||||||
// MP: This should be checked on the current folder instead of just
|
|
||||||
// the content section.
|
|
||||||
final boolean newItem = permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.CREATE_NEW, folder);
|
|
||||||
|
|
||||||
if (!newItem) {
|
|
||||||
browseMode(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
createFolderAction.setVisible(state, newItem);
|
|
||||||
newItemForm.setVisible(state, newItem);
|
|
||||||
|
|
||||||
final boolean editItem = permissionChecker.isPermitted(
|
|
||||||
ItemPrivileges.EDIT, folder);
|
|
||||||
|
|
||||||
editFolderAction.setVisible(state, editItem);
|
|
||||||
// chooseLabel.setVisible(state, editItem);
|
|
||||||
// editFolderSegment.setVisible(state, editItem);
|
|
||||||
|
|
||||||
if (permissionChecker.isPermitted(ItemPrivileges.ADMINISTER, folder)) {
|
|
||||||
permissionsSegment.setVisible(state, true);
|
|
||||||
} else {
|
|
||||||
permissionsSegment.setVisible(state, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void browseMode(final PageState state) {
|
|
||||||
browseSegment.setVisible(state, true);
|
|
||||||
permissionsSegment.setVisible(state, true);
|
|
||||||
chooseLabel.setVisible(state, false);
|
|
||||||
contentLabel.setVisible(state, true);
|
|
||||||
folderPath.setVisible(state, true);
|
|
||||||
newItemSegment.setVisible(state, false);
|
|
||||||
newFolderSegment.setVisible(state, false);
|
|
||||||
editFolderSegment.setVisible(state, false);
|
|
||||||
|
|
||||||
typeSelectionModel.clearSelection(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void newItemMode(final PageState state) {
|
|
||||||
permissionsSegment.setVisible(state, false);
|
|
||||||
newItemSegment.setVisible(state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void newFolderMode(final PageState state) {
|
|
||||||
permissionsSegment.setVisible(state, false);
|
|
||||||
newFolderSegment.setVisible(state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void submitted(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
if (event.getSource() == folderCreator
|
|
||||||
&& folderCreator.isCancelled(state)) {
|
|
||||||
browseMode(state);
|
|
||||||
throw new FormProcessException(new GlobalizedMessage(
|
|
||||||
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
|
|
||||||
} else if (event.getSource() == folderEditor
|
|
||||||
&& folderEditor.isCancelled(state)) {
|
|
||||||
browseMode(state);
|
|
||||||
throw new FormProcessException(new GlobalizedMessage(
|
|
||||||
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
|
|
||||||
} else if (event.getSource() == folderManipulator.getTargetSelector()) {
|
|
||||||
// This only works if this submission listener is run
|
|
||||||
// after the target selector's one
|
|
||||||
if (!folderManipulator.getTargetSelector().isVisible(state)) {
|
|
||||||
browseMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final Object source = event.getSource();
|
|
||||||
if (source == newItemForm) {
|
|
||||||
final Long typeID = newItemForm.getTypeID(state);
|
|
||||||
typeSelectionModel.setSelectedKey(state, typeID);
|
|
||||||
newItemMode(state);
|
|
||||||
} else if (source == folderCreator || source == folderEditor) {
|
|
||||||
browseMode(state);
|
|
||||||
} else if (source == folderManipulator.getItemView()) {
|
|
||||||
// Hide everything except for the browseSeg
|
|
||||||
permissionsSegment.setVisible(state, false);
|
|
||||||
chooseLabel.setVisible(state, true);
|
|
||||||
contentLabel.setVisible(state, false);
|
|
||||||
folderPath.setVisible(state, false);
|
|
||||||
} else if (source == folderManipulator.getTargetSelector()) {
|
|
||||||
browseMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stateChanged(final ChangeEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
if (event.getSource().equals(typeSelectionModel)) {
|
|
||||||
if (!typeSelectionModel.isSelected(state)) {
|
|
||||||
browseMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final Object source = event.getSource();
|
|
||||||
if (source == createFolderAction) {
|
|
||||||
newFolderMode(state);
|
|
||||||
} else if (source == editFolderAction) {
|
|
||||||
permissionsSegment.setVisible(state, false);
|
|
||||||
editFolderSegment.setVisible(state, true);
|
|
||||||
}
|
|
||||||
// else if (source == togglePrivateAction) {
|
|
||||||
// togglePermissions(state);
|
|
||||||
// }
|
|
||||||
// } else if (source == m_setHomeFolderAction) {
|
|
||||||
// User user = Web.getWebContext().getUser();
|
|
||||||
// Folder folder = m_folder.getFolder(state);
|
|
||||||
// user = (User) DomainObjectFactory.newInstance(user.getOID());
|
|
||||||
// Folder.setUserHomeFolder(user, folder);
|
|
||||||
// } else if (source == m_removeHomeFolderAction) {
|
|
||||||
// User user = Web.getWebContext().getUser();
|
|
||||||
// ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
// UserHomeFolderMap map = UserHomeFolderMap
|
|
||||||
// .findUserHomeFolderMap(user, section);
|
|
||||||
// if (map != null) {
|
|
||||||
// map.delete();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void togglePermissions(final PageState state) {
|
|
||||||
final Folder currentFolder = folderRequestLocal.getFolder(state);
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
permissionChecker.checkPermission(ItemPrivileges.ADMINISTER,
|
|
||||||
currentFolder);
|
|
||||||
|
|
||||||
permissionsPane.reset(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset(final PageState state) {
|
|
||||||
browseMode(state);
|
|
||||||
folderManipulator.reset(state);
|
|
||||||
// switching between folders used to keep showing the permission pane
|
|
||||||
// in the same perm mode (direct or inherited) regardless
|
|
||||||
// of the folder status
|
|
||||||
permissionsPane.reset(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final FolderManipulator getManipulator() {
|
|
||||||
return folderManipulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final CMSPermissionsPane getPermissionsPane() {
|
|
||||||
return permissionsPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPermissionLinkVis(final PageState state) {
|
|
||||||
// final Folder currentFolder = folderRequestLocal.getFolder(state);
|
|
||||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
// final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
// PermissionChecker.class);
|
|
||||||
// if (!permissionChecker.isPermitted(ItemPrivileges.ADMINISTER,
|
|
||||||
// currentFolder)) {
|
|
||||||
// togglePrivateAction.setVisible(state, false);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SectionNewItemForm extends NewItemForm {
|
|
||||||
|
|
||||||
public SectionNewItemForm(final String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContentSection getContentSection(final PageState state) {
|
|
||||||
return CMS.getContext().getContentSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getting the GlobalizedMessage using a CMS Class targetBundle.
|
|
||||||
*
|
|
||||||
* @param key The resource key
|
|
||||||
*
|
|
||||||
* @pre ( key != null )
|
|
||||||
*/
|
|
||||||
private static GlobalizedMessage globalize(final String key) {
|
|
||||||
return ContentSectionPage.globalize(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.item.ContentItemRequestLocal;
|
|
||||||
import com.arsdigita.dispatcher.AccessDeniedException;
|
|
||||||
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Justin Ross <jross@redhat.com>
|
|
||||||
*/
|
|
||||||
public class FormSecurityListener implements FormSubmissionListener {
|
|
||||||
|
|
||||||
private final String m_action;
|
|
||||||
private final ContentItemRequestLocal m_item;
|
|
||||||
|
|
||||||
public FormSecurityListener(final String action,
|
|
||||||
final ContentItemRequestLocal item) {
|
|
||||||
Assert.exists(action, String.class);
|
|
||||||
|
|
||||||
m_action = action;
|
|
||||||
m_item = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormSecurityListener(final String action) {
|
|
||||||
this(action, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void submitted(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
|
|
||||||
if (m_item == null) {
|
|
||||||
if (permissionChecker.isPermitted(m_action)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final ContentItem item = m_item.getContentItem(state);
|
|
||||||
|
|
||||||
if (permissionChecker.isPermitted(m_action, item)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new AccessDeniedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleComponent;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.ui.UI;
|
|
||||||
import com.arsdigita.ui.admin.AdminUiConstants;
|
|
||||||
import com.arsdigita.ui.login.LoginServlet;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.core.CoreConstants;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
import org.libreccm.web.ApplicationManager;
|
|
||||||
import org.libreccm.web.ApplicationRepository;
|
|
||||||
import org.libreccm.web.ApplicationType;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Global navigation elements for the CMS admin UIs.</p>
|
|
||||||
*
|
|
||||||
* @author Justin Ross <jross@redhat.com>
|
|
||||||
*/
|
|
||||||
// Made public (instead of unspecified, resulting in protected) in 6.6.8
|
|
||||||
public class GlobalNavigation extends SimpleComponent {
|
|
||||||
|
|
||||||
|
|
||||||
private final String m_adminPath;
|
|
||||||
private final String m_centerPath;
|
|
||||||
private final String m_changePasswordPath;
|
|
||||||
private final String m_helpPath;
|
|
||||||
private final String m_signOutPath;
|
|
||||||
private final String m_wspcPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public GlobalNavigation() {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ApplicationManager appManager = cdiUtil.findBean(
|
|
||||||
ApplicationManager.class);
|
|
||||||
final ApplicationRepository appRepo = cdiUtil.findBean(
|
|
||||||
ApplicationRepository.class);
|
|
||||||
final Map<String, ApplicationType> appTypes = appManager
|
|
||||||
.getApplicationTypes();
|
|
||||||
final ApplicationType adminAppType = appTypes.get(
|
|
||||||
AdminUiConstants.ADMIN_APP_TYPE);
|
|
||||||
final List<CcmApplication> adminApps = appRepo.findByType(adminAppType
|
|
||||||
.name());
|
|
||||||
final ApplicationType contentCenterAppType = appTypes.get(
|
|
||||||
CmsConstants.CONTENT_CENTER_APP_TYPE);
|
|
||||||
final List<CcmApplication> contentCenterApps = appRepo.findByType(
|
|
||||||
contentCenterAppType.name());
|
|
||||||
|
|
||||||
m_adminPath = adminApps.get(0).getPrimaryUrl();
|
|
||||||
m_centerPath = contentCenterApps.get(0).getPrimaryUrl();
|
|
||||||
m_changePasswordPath = LoginServlet.getChangePasswordPageURL();
|
|
||||||
m_helpPath = "/nowhere"; // We don't have this yet XXX.
|
|
||||||
m_signOutPath = LoginServlet.getLogoutPageURL();
|
|
||||||
m_wspcPath = UI.getWorkspaceURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateXML(final PageState state, final Element parent) {
|
|
||||||
if (isVisible(state)) {
|
|
||||||
final HttpServletRequest sreq = state.getRequest();
|
|
||||||
|
|
||||||
final Element nav = parent.newChildElement("cms:globalNavigation",
|
|
||||||
CMS.CMS_XML_NS);
|
|
||||||
final String centerTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.content_center", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final String adminTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.admin_center", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final String wspcTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.my_workspace", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final String signOutTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.sign_out", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final String helpTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.help", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final String changePasswordTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.change_password", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
|
|
||||||
link(sreq, nav, "cms:contentCenter", m_centerPath, centerTitle);
|
|
||||||
|
|
||||||
/* If the current user has admin permissions, insert a link to the admin center */
|
|
||||||
if (CdiUtil.createCdiUtil().findBean(PermissionChecker.class)
|
|
||||||
.isPermitted(CoreConstants.PRIVILEGE_ADMIN)) {
|
|
||||||
link(sreq, nav, "cms:adminCenter", m_adminPath, adminTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
link(sreq, nav, "cms:workspace", m_wspcPath, wspcTitle);
|
|
||||||
link(sreq, nav, "cms:changePassword", m_changePasswordPath,
|
|
||||||
changePasswordTitle);
|
|
||||||
link(sreq, nav, "cms:signOut", m_signOutPath, signOutTitle);
|
|
||||||
link(sreq, nav, "cms:help", m_helpPath, helpTitle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param sreq
|
|
||||||
* @param parent
|
|
||||||
* @param name
|
|
||||||
* @param path
|
|
||||||
* @param title
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static Element link(final HttpServletRequest sreq,
|
|
||||||
final Element parent,
|
|
||||||
final String name,
|
|
||||||
final String path,
|
|
||||||
final String title) {
|
|
||||||
final Element link = parent.newChildElement(name, CMS.CMS_XML_NS);
|
|
||||||
|
|
||||||
link.addAttribute("href", URL.there(sreq, path).toString());
|
|
||||||
link.addAttribute("title", title);
|
|
||||||
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,265 +0,0 @@
|
||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.FormModel;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.List;
|
|
||||||
import com.arsdigita.bebop.MapComponentSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.SegmentedPanel;
|
|
||||||
import com.arsdigita.bebop.SegmentedPanel.Segment;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.ChangeEvent;
|
|
||||||
import com.arsdigita.bebop.event.ChangeListener;
|
|
||||||
import com.arsdigita.bebop.list.ListModel;
|
|
||||||
import com.arsdigita.bebop.list.ListModelBuilder;
|
|
||||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.util.GlobalizationUtil;
|
|
||||||
import com.arsdigita.toolbox.ui.ActionGroup;
|
|
||||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
|
||||||
import com.arsdigita.toolbox.ui.Section;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.util.LockableImpl;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link LayoutPanel} to insert into {@link ContentSectionPage}.
|
|
||||||
*
|
|
||||||
* @author Sören Bernstein <quasi@quasiweb.de>
|
|
||||||
*/
|
|
||||||
public class ImagesPane extends LayoutPanel implements Resettable {
|
|
||||||
|
|
||||||
public static final Logger S_LOG = Logger.getLogger(ImagesPane.class);
|
|
||||||
private final StringParameter m_imageComponentKey;
|
|
||||||
private final MapComponentSelectionModel m_imageComponent;
|
|
||||||
private final ImageComponentAdminListener m_adminListener;
|
|
||||||
final private SegmentedPanel m_body;
|
|
||||||
private HashMap<String, Segment> m_bodySegments = new HashMap();
|
|
||||||
private final ResettableParameterSingleSelectionModel m_model;
|
|
||||||
private final List m_links;
|
|
||||||
private final LinksSection m_modes;
|
|
||||||
|
|
||||||
public ImagesPane() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
m_model = new ResettableParameterSingleSelectionModel(new
|
|
||||||
StringParameter(List.SELECTED));
|
|
||||||
m_model.setDefaultSelection(ImageComponent.LIBRARY);
|
|
||||||
m_model.addChangeListener(new ImageAdminSelectionListener());
|
|
||||||
|
|
||||||
m_links = new List(new ImageAdminListModelBuilder());
|
|
||||||
m_links.setSelectionModel(m_model);
|
|
||||||
|
|
||||||
final SimpleContainer left = new SimpleContainer();
|
|
||||||
setLeft(left);
|
|
||||||
|
|
||||||
m_modes = new LinksSection();
|
|
||||||
left.add(m_modes);
|
|
||||||
|
|
||||||
m_body = new SegmentedPanel();
|
|
||||||
setBody(m_body);
|
|
||||||
|
|
||||||
m_imageComponentKey = new StringParameter("imageComponent");
|
|
||||||
|
|
||||||
final ParameterSingleSelectionModel componentModel = new
|
|
||||||
ParameterSingleSelectionModel(m_imageComponentKey);
|
|
||||||
m_imageComponent = new MapComponentSelectionModel(componentModel,
|
|
||||||
new HashMap());
|
|
||||||
|
|
||||||
final Map selectors = m_imageComponent.getComponentsMap();
|
|
||||||
m_adminListener = new ImageComponentAdminListener(m_imageComponent, this);
|
|
||||||
|
|
||||||
// Image library component
|
|
||||||
final ImageLibraryComponent library = new
|
|
||||||
ImageLibraryComponent(ImageComponent.ADMIN_IMAGES);
|
|
||||||
library.getForm().addInitListener(m_adminListener);
|
|
||||||
library.getForm().addProcessListener(m_adminListener);
|
|
||||||
selectors.put(ImageComponent.LIBRARY, library);
|
|
||||||
m_bodySegments.put(ImageComponent.LIBRARY, m_body.addSegment(
|
|
||||||
new Label(GlobalizationUtil.globalize(
|
|
||||||
"cms.contentasset.image.ui.image_library")),
|
|
||||||
library));
|
|
||||||
|
|
||||||
// Image upload component
|
|
||||||
final ImageUploadComponent upload = new
|
|
||||||
ImageUploadComponent(ImageComponent.ADMIN_IMAGES);
|
|
||||||
upload.getForm().addInitListener(m_adminListener);
|
|
||||||
upload.getForm().addSubmissionListener(m_adminListener);
|
|
||||||
upload.getForm().addProcessListener(m_adminListener);
|
|
||||||
selectors.put(ImageComponent.UPLOAD, upload);
|
|
||||||
m_bodySegments.put(ImageComponent.UPLOAD, m_body.addSegment(
|
|
||||||
new Label(GlobalizationUtil.globalize(
|
|
||||||
"cms.contentasset.image.ui.image_upload")),
|
|
||||||
upload));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
Iterator<String> keys = m_bodySegments.keySet().iterator();
|
|
||||||
|
|
||||||
while (keys.hasNext()) {
|
|
||||||
String key = keys.next();
|
|
||||||
page.setVisibleDefault(m_bodySegments.get(key),
|
|
||||||
m_model.getDefaultSelection().equals(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
page.addComponentStateParam(this, m_imageComponentKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets this pane and all its resettable components.
|
|
||||||
*
|
|
||||||
* @param state Page state
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final void reset(final PageState state) {
|
|
||||||
super.reset(state);
|
|
||||||
|
|
||||||
m_model.reset(state);
|
|
||||||
this.setActiveImageComponent(state, m_model.getDefaultSelection());
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setActiveImageComponent(PageState state, String activeComp) {
|
|
||||||
|
|
||||||
Iterator<String> keys = m_bodySegments.keySet().iterator();
|
|
||||||
m_imageComponent.setSelectedKey(state, activeComp);
|
|
||||||
|
|
||||||
while (keys.hasNext()) {
|
|
||||||
|
|
||||||
String key = keys.next();
|
|
||||||
final boolean visibility = key.equals(activeComp);
|
|
||||||
state.setVisible(m_bodySegments.get(key), visibility);
|
|
||||||
|
|
||||||
for (int index = 0; index < m_bodySegments.get(key).size(); index++) {
|
|
||||||
|
|
||||||
Component component = m_bodySegments.get(key).get(index);
|
|
||||||
|
|
||||||
// Reset all components if they are of type Resettable
|
|
||||||
if (component instanceof Resettable) {
|
|
||||||
((Resettable) component).reset(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set visibility
|
|
||||||
component.setVisible(state, visibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private class ResettableParameterSingleSelectionModel
|
|
||||||
extends ParameterSingleSelectionModel
|
|
||||||
implements Resettable {
|
|
||||||
|
|
||||||
private String defaultKey;
|
|
||||||
|
|
||||||
public ResettableParameterSingleSelectionModel(ParameterModel m) {
|
|
||||||
super(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultSelection(String selKey) {
|
|
||||||
this.defaultKey = selKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultSelection() {
|
|
||||||
return defaultKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset(PageState state) {
|
|
||||||
|
|
||||||
if (Assert.isEnabled()) {
|
|
||||||
final FormModel model = state.getPage().getStateModel();
|
|
||||||
Assert.isTrue(model.containsFormParam(getStateParameter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
state.setValue(getStateParameter(), this.defaultKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private class ImageAdminListModel implements ListModel {
|
|
||||||
|
|
||||||
private ArrayList<String> m_keys;
|
|
||||||
private int m_index = -1;
|
|
||||||
|
|
||||||
public ImageAdminListModel(ArrayList keys) {
|
|
||||||
m_keys = keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean next() {
|
|
||||||
return (m_index++ < m_keys.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getElement() {
|
|
||||||
return GlobalizationUtil.globalize(
|
|
||||||
"cms.contentasset.image.ui.image_" + m_keys.get(m_index)).localize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return m_keys.get(m_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ImageAdminListModelBuilder extends LockableImpl
|
|
||||||
implements ListModelBuilder {
|
|
||||||
|
|
||||||
public ListModel makeModel(final List list, final PageState state) {
|
|
||||||
ArrayList<String> keys = new ArrayList(2);
|
|
||||||
keys.add(ImageComponent.LIBRARY);
|
|
||||||
keys.add(ImageComponent.UPLOAD);
|
|
||||||
return new ImageAdminListModel(keys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ImageAdminSelectionListener implements ChangeListener {
|
|
||||||
|
|
||||||
public final void stateChanged(final ChangeEvent e) {
|
|
||||||
S_LOG.debug("Selection state changed; I may change "
|
|
||||||
+"the body's visible pane");
|
|
||||||
|
|
||||||
final PageState state = e.getPageState();
|
|
||||||
|
|
||||||
// ImagesPane.this.reset(state);
|
|
||||||
|
|
||||||
if (m_model.isSelected(state)) {
|
|
||||||
S_LOG.debug("The selection model is selected; displaying "
|
|
||||||
+"the item pane");
|
|
||||||
|
|
||||||
ImagesPane.this.setActiveImageComponent(
|
|
||||||
state,
|
|
||||||
state.getControlEventValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LinksSection extends Section {
|
|
||||||
|
|
||||||
LinksSection() {
|
|
||||||
setHeading(GlobalizationUtil.globalize(
|
|
||||||
"cms.contentasset.image.ui.images"));
|
|
||||||
|
|
||||||
final ActionGroup group = new ActionGroup();
|
|
||||||
setBody(group);
|
|
||||||
|
|
||||||
group.setSubject(m_links);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper around the {@link ItemSearchSection} which embeds the form section
|
|
||||||
* in a form.
|
|
||||||
*
|
|
||||||
* @author Stanislav Freidin (sfreidin@arsdigita.com)
|
|
||||||
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ItemSearch extends Form implements Resettable {
|
|
||||||
|
|
||||||
public static final String SINGLE_TYPE_PARAM = ItemSearchSection.SINGLE_TYPE_PARAM;
|
|
||||||
|
|
||||||
private ItemSearchSection itemSearchSection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSearch</code> component Default to limit the
|
|
||||||
* search to current content section
|
|
||||||
*
|
|
||||||
* @param context the context for the retrieved items. Should be
|
|
||||||
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
|
|
||||||
*/
|
|
||||||
public ItemSearch(String context) {
|
|
||||||
this(context, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSearch</code> component
|
|
||||||
*
|
|
||||||
* @param context the context for the retrieved items. Should be
|
|
||||||
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
|
|
||||||
* @param limitToContentSection limit the search to the current content
|
|
||||||
* section
|
|
||||||
*/
|
|
||||||
public ItemSearch(final String context,
|
|
||||||
final boolean limitToContentSection) {
|
|
||||||
super("itemSearch", new SimpleContainer());
|
|
||||||
//setMethod("GET");
|
|
||||||
itemSearchSection = createSearchSection(context, limitToContentSection);
|
|
||||||
super.add(itemSearchSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ItemSearchSection createSearchSection(final String context,
|
|
||||||
boolean limitToContentSection) {
|
|
||||||
return new ItemSearchSection(context, limitToContentSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset(final PageState state) {
|
|
||||||
itemSearchSection.reset(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.Container;
|
|
||||||
import com.arsdigita.bebop.Resettable;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.FormSection;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentType;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.search.ItemQueryComponent;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import com.arsdigita.search.ui.ResultsPane;
|
|
||||||
import com.arsdigita.search.ui.QueryGenerator;
|
|
||||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a form for specifying search parameters, as well as a
|
|
||||||
* {@link com.arsdigita.search.ui.ResultsPane} which will perform the search and
|
|
||||||
* display the results
|
|
||||||
*
|
|
||||||
* @author Stanislav Freidin (sfreidin@arsdigita.com)
|
|
||||||
* @version $Id: ItemSearchSection.java 1940 2009-05-29 07:15:05Z terry $
|
|
||||||
*/
|
|
||||||
public class ItemSearchSection extends FormSection implements Resettable {
|
|
||||||
|
|
||||||
public static final String SINGLE_TYPE_PARAM = "single_type";
|
|
||||||
|
|
||||||
private ItemQueryComponent itemQueryComponent;
|
|
||||||
private Component resultsComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSearchSection</code> component
|
|
||||||
*
|
|
||||||
* @param context the context for the retrieved items. Should be
|
|
||||||
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
|
|
||||||
* @param limitToContentSection limit the search to the current content
|
|
||||||
* section
|
|
||||||
*/
|
|
||||||
public ItemSearchSection(final String context,
|
|
||||||
final boolean limitToContentSection) {
|
|
||||||
this(null, context, limitToContentSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new <code>ItemSearchSection</code> component
|
|
||||||
*
|
|
||||||
* @param context the context for the retrieved items. Should be
|
|
||||||
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
|
|
||||||
* @param name The name of the search parameter for the particular
|
|
||||||
* FormSection
|
|
||||||
* @param limitToContentSection limit the search to the current content
|
|
||||||
* section
|
|
||||||
*/
|
|
||||||
public ItemSearchSection(final String name,
|
|
||||||
final String context,
|
|
||||||
final boolean limitToContentSection) {
|
|
||||||
this(name, context, limitToContentSection, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemSearchSection(final String name,
|
|
||||||
final String context,
|
|
||||||
final boolean limitToContentSection,
|
|
||||||
final ContentType type) {
|
|
||||||
super(new SimpleContainer());
|
|
||||||
final String thisName;
|
|
||||||
if (name == null) {
|
|
||||||
thisName = "itemSearch";
|
|
||||||
} else {
|
|
||||||
thisName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null) {
|
|
||||||
itemQueryComponent = createQueryGenerator(context,
|
|
||||||
limitToContentSection);
|
|
||||||
} else {
|
|
||||||
itemQueryComponent = createQueryGenerator(context,
|
|
||||||
limitToContentSection,
|
|
||||||
type);
|
|
||||||
}
|
|
||||||
resultsComponent = createResultsPane(itemQueryComponent);
|
|
||||||
|
|
||||||
LayoutPanel searchPanel = new LayoutPanel();
|
|
||||||
searchPanel.setLeft(itemQueryComponent);
|
|
||||||
searchPanel.setBody(resultsComponent);
|
|
||||||
this.add(searchPanel);
|
|
||||||
|
|
||||||
addQueryGenerator(this);
|
|
||||||
addResultsPane(this);
|
|
||||||
addFormListener();
|
|
||||||
|
|
||||||
setClassAttr("itemSearch");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset(final PageState state) {
|
|
||||||
resultsComponent.setVisible(state, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ItemQueryComponent createQueryGenerator(
|
|
||||||
final String context, final boolean limitToContentSection) {
|
|
||||||
return new ItemQueryComponent(context, limitToContentSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ItemQueryComponent createQueryGenerator(
|
|
||||||
final String context,
|
|
||||||
final boolean limitToContentSection,
|
|
||||||
final ContentType type) {
|
|
||||||
|
|
||||||
return new ItemQueryComponent(context, limitToContentSection, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Component createResultsPane(QueryGenerator generator) {
|
|
||||||
ResultsPane pane = new ResultsPane(generator);
|
|
||||||
pane.setRelativeURLs(true);
|
|
||||||
pane.setSearchHelpMsg(new GlobalizedMessage("cms.ui.search.help",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
pane.setNoResultsMsg(new GlobalizedMessage("cms.ui.search.no_results",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
return pane;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addResultsPane(final Container container) {
|
|
||||||
container.add(resultsComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addQueryGenerator(final Container container) {
|
|
||||||
container.add(itemQueryComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processQuery(final PageState state) {
|
|
||||||
resultsComponent.setVisible(state, itemQueryComponent.hasQuery(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addFormListener() {
|
|
||||||
addProcessListener(new SearchFormProcessListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide results by default
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
page.setVisibleDefault(resultsComponent, false);
|
|
||||||
page.addGlobalStateParam(new BigDecimalParameter(SINGLE_TYPE_PARAM));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the "keywords" and "content types" widgets
|
|
||||||
*/
|
|
||||||
private class SearchFormProcessListener implements FormProcessListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
PageState s = event.getPageState();
|
|
||||||
processQuery(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.OptionGroup;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Migrated from the {@code DataQueryOptionPrintListener} in the old system.
|
|
||||||
* Renamed and refactored to operate on a list.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*
|
|
||||||
* @param <T> Type of the objects in the list.
|
|
||||||
*/
|
|
||||||
public abstract class ListOptionPrintListener<T> implements PrintListener {
|
|
||||||
|
|
||||||
public ListOptionPrintListener() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract List<T> getDataQuery(final PageState state);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final OptionGroup target = (OptionGroup) event.getTarget();
|
|
||||||
final List<T> dataQuery = getDataQuery(state);
|
|
||||||
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
dataQuery.forEach(item -> target.addOption(
|
|
||||||
new Option(getKey(item),
|
|
||||||
getValue(item))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String getKey(final T object);
|
|
||||||
|
|
||||||
public String getValue(final T object) {
|
|
||||||
return getKey(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,295 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.CheckboxGroup;
|
|
||||||
import com.arsdigita.bebop.form.Hidden;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.OptionGroup;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.Widget;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.libreccm.core.UnexpectedErrorException;
|
|
||||||
import org.libreccm.security.Party;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form for adding multiple parties to a role.
|
|
||||||
*
|
|
||||||
* @author Scott Seago (scott@arsdigita.com)
|
|
||||||
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
|
|
||||||
*/
|
|
||||||
public abstract class PartyAddForm extends SimpleContainer
|
|
||||||
implements FormInitListener, FormProcessListener {
|
|
||||||
|
|
||||||
private final static String SEARCH_QUERY = "searchQuery";
|
|
||||||
private final static String PARTIES = "parties";
|
|
||||||
private final static String SUBMIT = "addSubmit";
|
|
||||||
private final static String CANCEL = "addCancel";
|
|
||||||
|
|
||||||
private Widget searchWidget;
|
|
||||||
private RequestLocal queryRequestLocal;
|
|
||||||
|
|
||||||
private CMSContainer noMatchesContainer;
|
|
||||||
private CMSContainer matchesContainer;
|
|
||||||
|
|
||||||
private Form form;
|
|
||||||
private Hidden searchQueryField;
|
|
||||||
private Submit cancelButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private access prevents this constructor from ever being called directly.
|
|
||||||
*/
|
|
||||||
private PartyAddForm() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param searchWidget The widget on the search form that contains the value
|
|
||||||
* of the search string.
|
|
||||||
*/
|
|
||||||
public PartyAddForm(final Widget searchWidget) {
|
|
||||||
|
|
||||||
this();
|
|
||||||
|
|
||||||
this.searchWidget = searchWidget;
|
|
||||||
|
|
||||||
queryRequestLocal = new RequestLocal() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object initialValue(final PageState state) {
|
|
||||||
return makeQuery(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
form = makeForm();
|
|
||||||
|
|
||||||
final Label title = new Label(new GlobalizedMessage("cms.ui.matches",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
title.setFontWeight(Label.BOLD);
|
|
||||||
|
|
||||||
final Label label = new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.there_was_no_one_matching_the_search_criteria",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
label.setFontWeight("em");
|
|
||||||
|
|
||||||
noMatchesContainer = new CMSContainer();
|
|
||||||
noMatchesContainer.add(title);
|
|
||||||
noMatchesContainer.add(label);
|
|
||||||
super.add(noMatchesContainer);
|
|
||||||
|
|
||||||
matchesContainer = new CMSContainer();
|
|
||||||
matchesContainer.add(title);
|
|
||||||
matchesContainer.add(form);
|
|
||||||
super.add(matchesContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the form used to add parties.
|
|
||||||
*
|
|
||||||
* @return The form
|
|
||||||
*/
|
|
||||||
private Form makeForm() {
|
|
||||||
|
|
||||||
final CMSForm addPartyForm = new CMSForm("AddParties") {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isCancelled(final PageState state) {
|
|
||||||
return cancelButton.isSelected(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// This hidden field will store the search query. A hidden widget is
|
|
||||||
// used instead of a request local variable because the search query
|
|
||||||
// should only be updated when the search form is submitted.
|
|
||||||
searchQueryField = new Hidden(SEARCH_QUERY);
|
|
||||||
addPartyForm.add(searchQueryField, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
final Label hintLabel = new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.party_add_form.hint",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
addPartyForm.add(hintLabel, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
// Add the list of parties that can be added.
|
|
||||||
final CheckboxGroup partyCheckboxes = new CheckboxGroup(PARTIES);
|
|
||||||
partyCheckboxes.addValidationListener(new NotNullValidationListener());
|
|
||||||
try {
|
|
||||||
partyCheckboxes.addPrintListener(event -> {
|
|
||||||
final CheckboxGroup target = (CheckboxGroup) event.getTarget();
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
// Ensures that the init listener gets fired before the
|
|
||||||
// print listeners.
|
|
||||||
final FormData data = addPartyForm.getFormData(state);
|
|
||||||
addParties(state, target);
|
|
||||||
});
|
|
||||||
} catch (TooManyListenersException ex) {
|
|
||||||
throw new UnexpectedErrorException(ex);
|
|
||||||
}
|
|
||||||
addPartyForm.add(partyCheckboxes, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
// Submit and Cancel buttons.
|
|
||||||
final SimpleContainer buttonContainer = new SimpleContainer();
|
|
||||||
final Submit submitButton = new Submit(SUBMIT,
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.save",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
buttonContainer.add(submitButton);
|
|
||||||
cancelButton = new Submit(CANCEL,
|
|
||||||
new GlobalizedMessage("cms.ui.cancel",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
buttonContainer.add(cancelButton);
|
|
||||||
addPartyForm.add(buttonContainer, ColumnPanel.FULL_WIDTH
|
|
||||||
| ColumnPanel.CENTER);
|
|
||||||
|
|
||||||
addPartyForm.addInitListener(this);
|
|
||||||
addPartyForm.addProcessListener(this);
|
|
||||||
|
|
||||||
return addPartyForm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the form for adding parties.
|
|
||||||
*
|
|
||||||
* @return The "add party" form
|
|
||||||
*/
|
|
||||||
public Form getForm() {
|
|
||||||
return form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the widget that contains the search string.
|
|
||||||
*
|
|
||||||
* @return The widget that contains the search string
|
|
||||||
*/
|
|
||||||
protected Widget getSearchWidget() {
|
|
||||||
return searchQueryField;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the form is cancelled, false otherwise.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return true if the form is cancelled, false otherwise.
|
|
||||||
*
|
|
||||||
* @pre ( state != null )
|
|
||||||
*/
|
|
||||||
public boolean isCancelled(final PageState state) {
|
|
||||||
return cancelButton.isSelected(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds parties to the option group.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param target The option group
|
|
||||||
*
|
|
||||||
* @pre ( state != null && target != null )
|
|
||||||
*/
|
|
||||||
private void addParties(final PageState state, final OptionGroup target) {
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final List<Party> parties = (List<Party>) queryRequestLocal.get(state);
|
|
||||||
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
for (final Party party : parties) {
|
|
||||||
target.addOption(new Option(
|
|
||||||
Long.toString(party.getPartyId()),
|
|
||||||
new Label(new GlobalizedMessage(party.getName()))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a {@link Object} that encapsulates search results.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected abstract List<Party> makeQuery(PageState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the search query in the hidden field.
|
|
||||||
*
|
|
||||||
* @param event The form event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
|
|
||||||
searchQueryField.setValue(state, searchWidget.getValue(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process listener for the "Add parties" form.
|
|
||||||
*
|
|
||||||
* @param event The form event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public abstract void process(FormSectionEvent event)
|
|
||||||
throws FormProcessException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the appropriate frame.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param parent The parent DOM element
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateXML(final PageState state, final Element parent) {
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final List<Party> searchResults = (List<Party>) queryRequestLocal.get(state);
|
|
||||||
|
|
||||||
if (searchResults.size() > 0) {
|
|
||||||
matchesContainer.generateXML(state, parent);
|
|
||||||
} else {
|
|
||||||
noMatchesContainer.generateXML(state, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form to search for parties to be added to a staff group.
|
|
||||||
*
|
|
||||||
* @author Scott Seago <sseago@redhat.com>
|
|
||||||
* @version $Id: PartySearchForm.java 1942 2009-05-29 07:53:23Z terry $
|
|
||||||
*/
|
|
||||||
public class PartySearchForm extends BaseForm {
|
|
||||||
|
|
||||||
private final TextField searchField;
|
|
||||||
|
|
||||||
public PartySearchForm() {
|
|
||||||
super("SearchParties", gz("cms.ui.search"));
|
|
||||||
|
|
||||||
addComponent(new Label(gz("cms.ui.search_prompt")));
|
|
||||||
|
|
||||||
searchField = new TextField(new StringParameter("query"));
|
|
||||||
searchField.setSize(40);
|
|
||||||
addComponent(searchField);
|
|
||||||
|
|
||||||
addAction(new Submit("finish", gz("cms.ui.search")));
|
|
||||||
addAction(new Cancel());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void register(final Page page) {
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
Assert.isTrue(page.stateContains(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextField getSearchWidget() {
|
|
||||||
return searchField;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,171 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 Permeance Technologies Pty Ltd. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.List;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.event.ChangeEvent;
|
|
||||||
import com.arsdigita.bebop.event.ChangeListener;
|
|
||||||
import com.arsdigita.bebop.list.ListModel;
|
|
||||||
import com.arsdigita.bebop.list.ListModelBuilder;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.cms.ui.report.ContentSectionSummaryTable;
|
|
||||||
import com.arsdigita.cms.ui.report.Report;
|
|
||||||
import com.arsdigita.cms.ui.report.ReportListModel;
|
|
||||||
import com.arsdigita.toolbox.ui.ActionGroup;
|
|
||||||
import com.arsdigita.toolbox.ui.Section;
|
|
||||||
import com.arsdigita.util.LockableImpl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pane that shows selectable reports and their results. A selectable list of
|
|
||||||
* reports is shown on the left-hand side, a selected report is shown as body.
|
|
||||||
*
|
|
||||||
* @author
|
|
||||||
* <a href="https://sourceforge.net/users/thomas-buckel/">thomas-buckel</a>
|
|
||||||
* @author
|
|
||||||
* <a href="https://sourceforge.net/users/tim-permeance/">tim-permeance</a>
|
|
||||||
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ReportPane extends BaseAdminPane<String> {
|
|
||||||
|
|
||||||
private final SingleSelectionModel<String> selectionModel;
|
|
||||||
private final java.util.List<Report> availableReports;
|
|
||||||
|
|
||||||
public ReportPane() {
|
|
||||||
availableReports = getReports();
|
|
||||||
|
|
||||||
selectionModel = new ParameterSingleSelectionModel<>(
|
|
||||||
new StringParameter(List.SELECTED));
|
|
||||||
selectionModel.addChangeListener(new SelectionListener());
|
|
||||||
setSelectionModel(selectionModel);
|
|
||||||
|
|
||||||
List m_reports = new List(new ReportListModelBuilder(availableReports));
|
|
||||||
m_reports.setSelectionModel(selectionModel);
|
|
||||||
|
|
||||||
final ReportsListSection reportsListSection = new ReportsListSection(
|
|
||||||
m_reports);
|
|
||||||
setLeft(reportsListSection);
|
|
||||||
|
|
||||||
// Register the actual components of the reports for later usage
|
|
||||||
for (Report report : availableReports) {
|
|
||||||
getBody().add(report.getComponent());
|
|
||||||
}
|
|
||||||
|
|
||||||
setIntroPane(new Label(gz("cms.ui.reports.intro")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List of available reports.
|
|
||||||
*/
|
|
||||||
private java.util.List<Report> getReports() {
|
|
||||||
java.util.List<Report> reports = new ArrayList<>();
|
|
||||||
reports.add(new Report("cms.ui.reports.css.reportName",
|
|
||||||
new ContentSectionSummaryTable()));
|
|
||||||
// Add other reports as required
|
|
||||||
|
|
||||||
Collections.sort(
|
|
||||||
reports,
|
|
||||||
(r1, r2) -> r1.getName().compareTo(r2.getName()));
|
|
||||||
|
|
||||||
return reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the report model that matches the given key.
|
|
||||||
*
|
|
||||||
* @param key Key to match.
|
|
||||||
*
|
|
||||||
* @return Report model that matches that given key, null if no matching
|
|
||||||
* report was found.
|
|
||||||
*/
|
|
||||||
private Report getReportByKey(final String key) {
|
|
||||||
for (Report report : availableReports) {
|
|
||||||
if (report.getKey().equals(key)) {
|
|
||||||
return report;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UI section for left-hand list of reports.
|
|
||||||
*/
|
|
||||||
private class ReportsListSection extends Section {
|
|
||||||
|
|
||||||
ReportsListSection(final List reports) {
|
|
||||||
setHeading(gz("cms.ui.reports.header"));
|
|
||||||
ActionGroup group = new ActionGroup();
|
|
||||||
setBody(group);
|
|
||||||
group.setSubject(reports);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SelectionListener for selected report. It shows the selected report in
|
|
||||||
* the body of this component.
|
|
||||||
*/
|
|
||||||
private class SelectionListener implements ChangeListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void stateChanged(final ChangeEvent event) {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
getBody().reset(state);
|
|
||||||
|
|
||||||
if (selectionModel.isSelected(state)) {
|
|
||||||
Report selectedReport = getReportByKey(selectionModel
|
|
||||||
.getSelectedKey(state).toString());
|
|
||||||
if (selectedReport != null) {
|
|
||||||
getBody().push(state, selectedReport.getComponent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ListModelBuilder creating a ReportListModel for a list of reports.
|
|
||||||
*/
|
|
||||||
private static class ReportListModelBuilder
|
|
||||||
extends LockableImpl
|
|
||||||
implements ListModelBuilder {
|
|
||||||
|
|
||||||
private final java.util.List<Report> reports;
|
|
||||||
|
|
||||||
private ReportListModelBuilder(final java.util.List<Report> reports) {
|
|
||||||
this.reports = reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final ListModel makeModel(final List list,
|
|
||||||
final PageState state) {
|
|
||||||
return new ReportListModel(reports);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,392 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.FormSection;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.PropertyEditor;
|
|
||||||
import com.arsdigita.bebop.PropertyEditorModel;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.ComponentAccess;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends {@link com.arsdigita.bebop.PropertyEditor} to provide access control
|
|
||||||
* features. Each link may be associated with a {@link
|
|
||||||
* com.arsdigita.toolbox.ui.ComponentAccess} object; if the current does not
|
|
||||||
* have sufficient privileges, the link will be hidden.
|
|
||||||
* <p>
|
|
||||||
* The simple use pattern for this component is as follows:
|
|
||||||
*
|
|
||||||
* <blockquote><pre><code>
|
|
||||||
* SecurityPropertyEditor editor = new SecurityPropertyEditor();
|
|
||||||
* editor.setDisplayComponent(new FooComponent());
|
|
||||||
* NameEditForm n = new NameEditForm();
|
|
||||||
* ComponentAccess ca1 = new ComponentAccess(n);
|
|
||||||
* ca1.addAccessCheck(WORKFLOW_ADMIN);
|
|
||||||
* ca1.addAccessCheck(CATEGORY_ADMIN);
|
|
||||||
* editor.add("name", "Edit Name", ca, n.getCancelButton());
|
|
||||||
* AddressEditForm a = new AddressEditForm();
|
|
||||||
* ComponentAccess ca2 = new ComponentAccess(a);
|
|
||||||
* editor.add("address", "Edit Address", ca2, a.getCancelButton());
|
|
||||||
* </code></pre></blockquote>
|
|
||||||
*
|
|
||||||
* @author Michael Pih (pihman@arsdigita.com)
|
|
||||||
* @author Stanislav Freidin (sfreidin@arsdigita.com)
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class SecurityPropertyEditor extends PropertyEditor {
|
|
||||||
|
|
||||||
private final Map<String, ComponentAccess> accessChecks;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new, empty <code>PropertyEditor</code>. The {@link
|
|
||||||
* #setDisplayComponent(Component)} method must be called before this
|
|
||||||
* component is locked.
|
|
||||||
*/
|
|
||||||
public SecurityPropertyEditor() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new, <code>PropertyEditor</code> with the given display
|
|
||||||
* component
|
|
||||||
*
|
|
||||||
* @param display The display component
|
|
||||||
*/
|
|
||||||
public SecurityPropertyEditor(final Component display) {
|
|
||||||
super(display);
|
|
||||||
accessChecks = new HashMap<>();
|
|
||||||
setModelBuilder(new AccessListModelBuilder());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a component to the property editor. The component will be completely
|
|
||||||
* invisible; it is up to the user to call {@link #showComponent(PageState,
|
|
||||||
* String)} to display the component, and to call {@link
|
|
||||||
* #showDisplayPane(PageState)} when the component needs to be hidden.
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the component; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param componentAccess The {@link ComponentAccess} object which contains
|
|
||||||
* the child component, along with security restrictions
|
|
||||||
*/
|
|
||||||
public void addComponent(final String key,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
super.addComponent(key, componentAccess.getComponent());
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a component to the list of links. It is up to the component to
|
|
||||||
* correctly call showDisplayPane when it's done.
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the component; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link
|
|
||||||
* @param componentAccess The component access
|
|
||||||
* @deprecated use addComponent(String,GlobalizedMessage,ComponentAccess)
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
public void addComponent(final String key,
|
|
||||||
final String label,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
addComponent(key, componentAccess);
|
|
||||||
getLabelsMap().put(key, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a component to the list of links. It is up to the component to
|
|
||||||
* correctly call showDisplayPane when it's done.
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the component; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link
|
|
||||||
* @param componentAccess The component access
|
|
||||||
*/
|
|
||||||
public void addComponent(final String key,
|
|
||||||
final GlobalizedMessage label,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
addComponent(key, componentAccess);
|
|
||||||
getLabelsMap().put(key, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify a new {@link ComponentAccess} for a component which has already
|
|
||||||
* been added to the <code>SecurityPropertyEditor</code>.
|
|
||||||
*
|
|
||||||
* @param key the key under which the component was added
|
|
||||||
* @param componentAccess the <code>ComponentAccess</code> instance that
|
|
||||||
* will determine when the link for the specified component should be
|
|
||||||
* visible
|
|
||||||
* @pre access.getComponent() == m_forms.get(key)
|
|
||||||
*/
|
|
||||||
public void setComponentAccess(final String key,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
Assert.isUnlocked(this);
|
|
||||||
final Component component = getComponent(key);
|
|
||||||
Assert.exists(component, "the specified component");
|
|
||||||
Assert.isTrue(componentAccess.getComponent().equals(component),
|
|
||||||
"The specified component does not match the component that"
|
|
||||||
+ " id already in the PropertyEditor");
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a form to the set of forms which could be used to edit the
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the form; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link to access the form
|
|
||||||
* @param componentAccess The form ComponentAccess
|
|
||||||
*
|
|
||||||
* @deprecated use add(String,GlobalizedMessage,ComponentAccess)
|
|
||||||
*/
|
|
||||||
public void add(final String key,
|
|
||||||
final String label,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
final Component component = componentAccess.getComponent();
|
|
||||||
if (component instanceof Form) {
|
|
||||||
final Form form = (Form) component;
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
add(key, label, form);
|
|
||||||
addSecurityListener(form);
|
|
||||||
} else if (component instanceof FormSection) {
|
|
||||||
final FormSection section = (FormSection) componentAccess.
|
|
||||||
getComponent();
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
add(key, label, section);
|
|
||||||
addSecurityListener(section);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The ComponentAccess object does "
|
|
||||||
+ "not contain a form section.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a form to the set of forms which could be used to edit the
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the form; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link to access the form
|
|
||||||
* @param componentAccess The form ComponentAccess
|
|
||||||
*/
|
|
||||||
public void add(final String key,
|
|
||||||
final GlobalizedMessage label,
|
|
||||||
final ComponentAccess componentAccess) {
|
|
||||||
final Component component = componentAccess.getComponent();
|
|
||||||
if (component instanceof Form) {
|
|
||||||
final Form form = (Form) component;
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
add(key, label, form);
|
|
||||||
addSecurityListener(form);
|
|
||||||
} else if (component instanceof FormSection) {
|
|
||||||
final FormSection section = (FormSection) componentAccess.
|
|
||||||
getComponent();
|
|
||||||
accessChecks.put(key, componentAccess);
|
|
||||||
add(key, label, section);
|
|
||||||
addSecurityListener(section);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The ComponentAccess object does "
|
|
||||||
+ "not contain a form section.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a form to the set of forms which could be used to edit the properties
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the form; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link to access the form.
|
|
||||||
* @param componentAccess The form ComponentAccess
|
|
||||||
* @param cancelButton The Cancel button on the form.
|
|
||||||
*
|
|
||||||
* @deprecated use add(String,GlobalizedMessage,ComponentAccess,Submit)
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
public void add(final String key,
|
|
||||||
final String label,
|
|
||||||
final ComponentAccess componentAccess,
|
|
||||||
final Submit cancelButton) {
|
|
||||||
add(key, label, componentAccess);
|
|
||||||
addCancelListener((FormSection) componentAccess.getComponent(),
|
|
||||||
cancelButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a form to the set of forms which could be used to edit the properties
|
|
||||||
*
|
|
||||||
* @param key The symbolic key for the form; must be unique for this
|
|
||||||
* <code>PropertyEditor</code>
|
|
||||||
* @param label The label for the link to access the form.
|
|
||||||
* @param componentAccess The form ComponentAccess
|
|
||||||
* @param cancelButton The Cancel button on the form.
|
|
||||||
*/
|
|
||||||
public void add(final String key,
|
|
||||||
final GlobalizedMessage label,
|
|
||||||
final ComponentAccess componentAccess,
|
|
||||||
final Submit cancelButton) {
|
|
||||||
add(key, label, componentAccess);
|
|
||||||
addCancelListener((FormSection) componentAccess.getComponent(),
|
|
||||||
cancelButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a submission listener to the form that will hide all components and
|
|
||||||
* show the display pane. This method should be used to add submission
|
|
||||||
* listeners to forms which are buried deep inside some component, and are
|
|
||||||
* not members of this <code>PropertyEditor</code>.
|
|
||||||
*
|
|
||||||
* @param form The form
|
|
||||||
*/
|
|
||||||
public void addSecurityListener(final FormSection form) {
|
|
||||||
form.addSubmissionListener(new FormSubmissionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void submitted(final FormSectionEvent event) throws
|
|
||||||
FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
// Cancel the form if the user does not pass the access checks.
|
|
||||||
final String key = (String) getList().getSelectedKey(state);
|
|
||||||
final ComponentAccess componentAccess
|
|
||||||
= (ComponentAccess) accessChecks.get(key);
|
|
||||||
|
|
||||||
if (key == null || componentAccess == null) {
|
|
||||||
// no components currently selected and therefore
|
|
||||||
// no access checks to run for visibility
|
|
||||||
// or
|
|
||||||
// there are no access restrictions on the form
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!componentAccess.canAccess()) {
|
|
||||||
showDisplayPane(state);
|
|
||||||
throw new FormProcessException(new GlobalizedMessage(
|
|
||||||
"cms.ui.insufficient_privileges",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all required listeners to the form to ensure that if the form is
|
|
||||||
* submitted successfully or cancelled, the display pane will be shown. This
|
|
||||||
* method should be used to add listeners to forms which are buried deep
|
|
||||||
* inside some component, and are not members of this
|
|
||||||
* <code>PropertyEditor</code>.
|
|
||||||
*
|
|
||||||
* @param form The form
|
|
||||||
* @param cancelButton the "Cancel" button on the form
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addListeners(final FormSection form,
|
|
||||||
final Submit cancelButton) {
|
|
||||||
addSecurityListener(form);
|
|
||||||
super.addListeners(form, cancelButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the map of keys to access checks
|
|
||||||
*
|
|
||||||
* @return Map of keys to access check
|
|
||||||
*/
|
|
||||||
protected final Map<String, ComponentAccess> getAccessMap() {
|
|
||||||
return accessChecks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an {@link SecurityPropertyEditor.AccessListModel} during each
|
|
||||||
* request
|
|
||||||
*/
|
|
||||||
protected static class AccessListModelBuilder extends DefaultModelBuilder {
|
|
||||||
|
|
||||||
public AccessListModelBuilder() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PropertyEditorModel makeModel(
|
|
||||||
final PropertyEditor propertyEditor, final PageState state) {
|
|
||||||
|
|
||||||
return new AccessListModel(
|
|
||||||
getProperties(propertyEditor),
|
|
||||||
((SecurityPropertyEditor) propertyEditor).getAccessMap(),
|
|
||||||
state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs access checks for each property; skips the properties that the
|
|
||||||
* user is not allowed to access
|
|
||||||
*/
|
|
||||||
protected static class AccessListModel extends DefaultModel {
|
|
||||||
|
|
||||||
private final Map<String, ComponentAccess> accessMap;
|
|
||||||
private final PageState state;
|
|
||||||
|
|
||||||
public AccessListModel(final Iterator iter,
|
|
||||||
final Map<String, ComponentAccess> accessMap,
|
|
||||||
final PageState state) {
|
|
||||||
super(iter);
|
|
||||||
this.accessMap = accessMap;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean next() {
|
|
||||||
|
|
||||||
while (super.next()) {
|
|
||||||
final Object key = getKey();
|
|
||||||
final ComponentAccess ca = accessMap.get(key.toString());
|
|
||||||
|
|
||||||
if (ca == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ca.canAccess()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, skip the property
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.ControlLink;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.List;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.list.ListModel;
|
|
||||||
import com.arsdigita.bebop.util.BebopConstants;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This list offers the option for the code to provide the developer with links
|
|
||||||
* to sort the given categories.
|
|
||||||
*
|
|
||||||
* NOTE: This UI currently does not scale well with large numbers of items since
|
|
||||||
* it just lists all of them. It would probably be nice to integrate a paginator
|
|
||||||
* as well to as to allow the user to move an item in large distances and to
|
|
||||||
* insert an item in the middle. Right now, when you add an item it is just
|
|
||||||
* placed at the end. However, if you want the item to appear in the middle then
|
|
||||||
* you must hit the "up" arrow n/2 times where n is the number of items in the
|
|
||||||
* list. This clearly is not a good setup.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Randy Graebner (randyg@alum.mit.edu)
|
|
||||||
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
|
|
||||||
*/
|
|
||||||
public abstract class SortableList extends List {
|
|
||||||
|
|
||||||
// It would be really nice if this used the save variable as is
|
|
||||||
// used by List but because List has it as private, we cannot do that.
|
|
||||||
private static final String SELECT_EVENT = "s";
|
|
||||||
protected static final String PREV_EVENT = "prev";
|
|
||||||
protected static final String NEXT_EVENT = "next";
|
|
||||||
public boolean m_sortItems;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This just makes a standard {@link SortableList}
|
|
||||||
*/
|
|
||||||
public SortableList(ParameterSingleSelectionModel model) {
|
|
||||||
this(model, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortableList(ParameterSingleSelectionModel model,
|
|
||||||
boolean suppressSort) {
|
|
||||||
super(model);
|
|
||||||
m_sortItems = !suppressSort;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This geneates the XML as specified by the arguments pass in to the
|
|
||||||
* constructor.
|
|
||||||
*/
|
|
||||||
public void generateXML(PageState state, Element parent) {
|
|
||||||
if (!isVisible(state)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// They want the special sort items
|
|
||||||
ListModel m = getModel(state);
|
|
||||||
|
|
||||||
if (!m.next()) {
|
|
||||||
super.generateXML(state, parent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// because m.next() returned true, we know there are items
|
|
||||||
// in the list
|
|
||||||
Element list = parent
|
|
||||||
.newChildElement("cms:sortableList", CMS.CMS_XML_NS);
|
|
||||||
exportAttributes(list);
|
|
||||||
|
|
||||||
Component c;
|
|
||||||
Object selKey = getSelectedKey(state);
|
|
||||||
int i = 0;
|
|
||||||
boolean hasNext;
|
|
||||||
do {
|
|
||||||
Element item = list.newChildElement(BebopConstants.BEBOP_CELL,
|
|
||||||
BEBOP_XML_NS);
|
|
||||||
if (m_sortItems) {
|
|
||||||
|
|
||||||
item.addAttribute("configure", "true");
|
|
||||||
}
|
|
||||||
String key = m.getKey();
|
|
||||||
Assert.exists(key);
|
|
||||||
|
|
||||||
// Converting both keys to String for comparison
|
|
||||||
// since ListModel.getKey returns a String
|
|
||||||
boolean selected = (selKey != null)
|
|
||||||
&& key.equals(selKey.toString());
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
item.addAttribute("selected", "selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
generateLabelXML(state, item,
|
|
||||||
new Label(new GlobalizedMessage(m.getElement()
|
|
||||||
.toString())), key, m.getElement());
|
|
||||||
|
|
||||||
hasNext = m.next();
|
|
||||||
|
|
||||||
// Add attributes containing URLs that fire control events
|
|
||||||
// for various portlet actions
|
|
||||||
try {
|
|
||||||
// Maybe add attribute containing URL for "move up" link
|
|
||||||
if (i > 0) {
|
|
||||||
state.setControlEvent(this, PREV_EVENT, key);
|
|
||||||
item.addAttribute("prevURL", state.stateAsURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maybe add attribute containing URL for "move down" link
|
|
||||||
if (hasNext) {
|
|
||||||
state.setControlEvent(this, NEXT_EVENT, key);
|
|
||||||
item.addAttribute("nextURL", state.stateAsURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new IllegalStateException("Caught IOException: "
|
|
||||||
+ ex.getMessage());
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
} while (hasNext);
|
|
||||||
|
|
||||||
state.clearControlEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void generateLabelXML(PageState state, Element parent,
|
|
||||||
Label label, String key, Object element) {
|
|
||||||
state.setControlEvent(this, SELECT_EVENT, key);
|
|
||||||
Component c = new ControlLink(label);
|
|
||||||
c.generateXML(state, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,286 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.RequestLocal;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.form.CheckboxGroup;
|
|
||||||
import com.arsdigita.bebop.form.Hidden;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.OptionGroup;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.Widget;
|
|
||||||
import com.arsdigita.bebop.parameters.NotNullValidationListener;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.libreccm.security.User;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form for adding multiple users to a role.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:pihman@arsdigita.com">Michael Pih</a>
|
|
||||||
* @author <a href="mailto:umathur@arsdigita.com">Uday Mathur</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public abstract class UserAddForm extends SimpleContainer
|
|
||||||
implements FormProcessListener {
|
|
||||||
|
|
||||||
private final static String SEARCH_QUERY = "searchQuery";
|
|
||||||
private final static String USERS = "users";
|
|
||||||
private final static String SUBMIT = "addSubmit";
|
|
||||||
private final static String CANCEL = "addCancel";
|
|
||||||
|
|
||||||
private final static String DQ_USER_ID = "userId";
|
|
||||||
private final static String DQ_NAME = "name";
|
|
||||||
|
|
||||||
private Widget m_search;
|
|
||||||
private RequestLocal m_query;
|
|
||||||
private String m_label;
|
|
||||||
private String m_submitText;
|
|
||||||
|
|
||||||
private CMSContainer m_noMatches;
|
|
||||||
private CMSContainer m_matches;
|
|
||||||
|
|
||||||
private Form m_form;
|
|
||||||
private Hidden m_searchQuery;
|
|
||||||
private CheckboxGroup m_users;
|
|
||||||
private Submit m_submit;
|
|
||||||
private Submit m_cancel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param search The widget on the search form that contains the value of
|
|
||||||
* the search string.
|
|
||||||
*/
|
|
||||||
public UserAddForm(final Widget search) {
|
|
||||||
this(search, "AddUsers");
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserAddForm(final Widget search, final String name) {
|
|
||||||
this(search, name,
|
|
||||||
"Check the box next to the name of the person(s) to assign.",
|
|
||||||
"Add Members");
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserAddForm(final Widget search,
|
|
||||||
final String name,
|
|
||||||
final String text,
|
|
||||||
final String submitText) {
|
|
||||||
m_label = text;
|
|
||||||
m_submitText = submitText;
|
|
||||||
m_search = search;
|
|
||||||
|
|
||||||
m_query = new RequestLocal() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object initialValue(final PageState state) {
|
|
||||||
return makeQuery(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
m_form = makeForm(name);
|
|
||||||
|
|
||||||
final Label title = new Label(new GlobalizedMessage("cms.ui.matches",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
title.setFontWeight(Label.BOLD);
|
|
||||||
|
|
||||||
final Label label = new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.there_was_no_one_matching_the_search_criteria",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
label.setFontWeight("em");
|
|
||||||
|
|
||||||
m_noMatches = new CMSContainer();
|
|
||||||
m_noMatches.add(title);
|
|
||||||
m_noMatches.add(label);
|
|
||||||
add(m_noMatches);
|
|
||||||
|
|
||||||
m_matches = new CMSContainer();
|
|
||||||
m_matches.add(title);
|
|
||||||
m_matches.add(m_form);
|
|
||||||
add(m_matches);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the form used to add users.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
*
|
|
||||||
* @return The form
|
|
||||||
*/
|
|
||||||
protected Form makeForm(final String name) {
|
|
||||||
final CMSForm form = new CMSForm(name) {
|
|
||||||
|
|
||||||
public final boolean isCancelled(final PageState state) {
|
|
||||||
return m_cancel.isSelected(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// This hidden field will store the search query. A hidden widget is
|
|
||||||
// used instead of a request local variable because the search query
|
|
||||||
// should only be updated when the search form is submitted.
|
|
||||||
m_searchQuery = new Hidden(SEARCH_QUERY);
|
|
||||||
form.add(m_searchQuery, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
Label l = new Label(m_label);
|
|
||||||
form.add(l, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
// Add the list of users that can be added.
|
|
||||||
m_users = new CheckboxGroup(USERS);
|
|
||||||
m_users.addValidationListener(new NotNullValidationListener());
|
|
||||||
try {
|
|
||||||
m_users.addPrintListener(new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(PrintEvent event) {
|
|
||||||
CheckboxGroup target = (CheckboxGroup) event.getTarget();
|
|
||||||
PageState state = event.getPageState();
|
|
||||||
// Ensures that the init listener gets fired before the
|
|
||||||
// print listeners.
|
|
||||||
FormData data = m_form.getFormData(state);
|
|
||||||
addUsers(state, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (TooManyListenersException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
form.add(m_users, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
// Submit and Cancel buttons.
|
|
||||||
SimpleContainer s = new SimpleContainer();
|
|
||||||
m_submit = new Submit(SUBMIT, m_submitText);
|
|
||||||
s.add(m_submit);
|
|
||||||
m_cancel = new Submit(CANCEL, "Cancel");
|
|
||||||
s.add(m_cancel);
|
|
||||||
form.add(s, ColumnPanel.FULL_WIDTH | ColumnPanel.CENTER);
|
|
||||||
|
|
||||||
form.addProcessListener(this);
|
|
||||||
|
|
||||||
return form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the form for adding users.
|
|
||||||
*
|
|
||||||
* @return The "add user" form
|
|
||||||
*/
|
|
||||||
public Form getForm() {
|
|
||||||
return m_form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the widget that contains the search string.
|
|
||||||
*
|
|
||||||
* @return The widget that contains the search string
|
|
||||||
*/
|
|
||||||
protected Widget getSearchWidget() {
|
|
||||||
return m_searchQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the form is cancelled, false otherwise.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return true if the form is cancelled, false otherwise.
|
|
||||||
*
|
|
||||||
* @pre ( state != null )
|
|
||||||
*/
|
|
||||||
public boolean isCancelled(final PageState state) {
|
|
||||||
return m_cancel.isSelected(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds users to the option group.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param target The option group
|
|
||||||
*
|
|
||||||
* @pre ( state != null && target != null )
|
|
||||||
*/
|
|
||||||
protected void addUsers(final PageState state, final OptionGroup target) {
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final List<User> users = (java.util.List<User>) m_query.get(state);
|
|
||||||
|
|
||||||
users.forEach(user -> target.addOption(
|
|
||||||
new Option(Long.toString(user.getPartyId()),
|
|
||||||
user.getName())));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a {@link List} that encapsulates search results.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected abstract List<User> makeQuery(final PageState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process listener for the "Add users" form.
|
|
||||||
*
|
|
||||||
* @param event The form event
|
|
||||||
*
|
|
||||||
* @throws com.arsdigita.bebop.FormProcessException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public abstract void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the appropriate frame.
|
|
||||||
*
|
|
||||||
* @param state The page state
|
|
||||||
* @param parent The parent DOM element
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateXML(final PageState state,
|
|
||||||
final Element parent) {
|
|
||||||
|
|
||||||
m_searchQuery.setValue(state, m_search.getValue(state));
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final List<User> searchResults = (List<User>) m_query.get(state);
|
|
||||||
|
|
||||||
if (searchResults.size() > 0) {
|
|
||||||
m_matches.generateXML(state, parent);
|
|
||||||
} else {
|
|
||||||
m_noMatches.generateXML(state, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Form to search for users to be added to a staff group.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:pihman@arsdigita.com">Michael Pih</a>
|
|
||||||
*/
|
|
||||||
public class UserSearchForm extends CMSForm {
|
|
||||||
|
|
||||||
private final static String SEARCH_LABEL = "Search";
|
|
||||||
|
|
||||||
private TextField m_search;
|
|
||||||
|
|
||||||
public UserSearchForm(String name) {
|
|
||||||
this(name,
|
|
||||||
new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.search_to_add_new_members",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserSearchForm(String name, Label heading) {
|
|
||||||
super(name, new ColumnPanel(3));
|
|
||||||
heading.setFontWeight(Label.BOLD);
|
|
||||||
add(heading, ColumnPanel.FULL_WIDTH);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.enter_first_name_last_name_andor_email_address",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
|
|
||||||
m_search = new TextField(new StringParameter("query"));
|
|
||||||
m_search.setSize(20);
|
|
||||||
add(m_search, ColumnPanel.RIGHT);
|
|
||||||
|
|
||||||
Submit submit = new Submit("submit");
|
|
||||||
submit.setButtonLabel(SEARCH_LABEL);
|
|
||||||
add(submit, ColumnPanel.LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextField getSearchWidget() {
|
|
||||||
return m_search;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.toolbox.ui.ProxyComponent;
|
|
||||||
import com.arsdigita.util.Assert;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.security.PermissionChecker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Justin Ross
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class VisibilityComponent extends ProxyComponent {
|
|
||||||
|
|
||||||
private final String m_action;
|
|
||||||
|
|
||||||
public VisibilityComponent(final Component child, final String action) {
|
|
||||||
super(child);
|
|
||||||
|
|
||||||
m_action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible(final PageState state) {
|
|
||||||
return super.isVisible(state) && hasPermission(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasPermission(final PageState state) {
|
|
||||||
Assert.exists(m_action, String.class);
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
|
||||||
PermissionChecker.class);
|
|
||||||
|
|
||||||
return permissionChecker.isPermitted(m_action);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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.arsdigita.cms.ui;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.toolbox.ui.ContextBar;
|
|
||||||
import com.arsdigita.web.URL;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.web.ApplicationRepository;
|
|
||||||
import org.libreccm.web.CcmApplication;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* The context bar of the content center UI.</p>
|
|
||||||
*
|
|
||||||
* @author Justin Ross
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
// Made public (instead of unspecified) in 6.6.8
|
|
||||||
public class WorkspaceContextBar extends ContextBar {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A logger instance, primarily to assist debugging .
|
|
||||||
*/
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
WorkspaceContextBar.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected List<Entry> entries(final PageState state) {
|
|
||||||
|
|
||||||
final List<Entry> entries = super.entries(state);
|
|
||||||
|
|
||||||
final String centerTitle = (String) new GlobalizedMessage(
|
|
||||||
"cms.ui.content_center", CmsConstants.CMS_BUNDLE).localize();
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ApplicationRepository appRepo = cdiUtil.findBean(
|
|
||||||
ApplicationRepository.class);
|
|
||||||
final List<CcmApplication> apps = appRepo.findByType(
|
|
||||||
CmsConstants.CONTENT_CENTER_APP_TYPE);
|
|
||||||
|
|
||||||
final String centerPath = apps.get(0).getPrimaryUrl();
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug("Got Url: " + centerPath);
|
|
||||||
}
|
|
||||||
final URL url = URL.there(state.getRequest(), centerPath);
|
|
||||||
entries.add(new Entry(centerTitle, url));
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,433 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.ColumnPanel;
|
|
||||||
import com.arsdigita.bebop.Form;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Text;
|
|
||||||
import com.arsdigita.bebop.event.FormInitListener;
|
|
||||||
import com.arsdigita.bebop.event.FormProcessListener;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormSubmissionListener;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.SingleSelect;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
|
|
||||||
import org.libreccm.core.UnexpectedErrorException;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic Form for manipulating assets.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T> The type of the asset.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractAssetForm<T extends Asset>
|
|
||||||
extends Form implements FormInitListener,
|
|
||||||
FormProcessListener,
|
|
||||||
FormSubmissionListener {
|
|
||||||
|
|
||||||
private static final String ASSET_TITLE = "asset-name";
|
|
||||||
|
|
||||||
private static final String ASSET_NAME = "asset-title";
|
|
||||||
|
|
||||||
private final AssetPane assetPane;
|
|
||||||
|
|
||||||
private final SingleSelectionModel<Long> selectionModel;
|
|
||||||
|
|
||||||
private BoxPanel showLocalePanel;
|
|
||||||
|
|
||||||
private SingleSelect showLocaleSelect;
|
|
||||||
|
|
||||||
private Submit showLocaleSubmit;
|
|
||||||
|
|
||||||
private BoxPanel addLocalePanel;
|
|
||||||
|
|
||||||
private SingleSelect addLocaleSelect;
|
|
||||||
|
|
||||||
private Submit addLocaleSubmit;
|
|
||||||
|
|
||||||
private TextField name;
|
|
||||||
|
|
||||||
private TextField title;
|
|
||||||
|
|
||||||
private SaveCancelSection saveCancelSection;
|
|
||||||
|
|
||||||
public AbstractAssetForm(final AssetPane assetPane) {
|
|
||||||
super("asset-form", new ColumnPanel(1));
|
|
||||||
|
|
||||||
this.assetPane = assetPane;
|
|
||||||
selectionModel = assetPane.getSelectedAssetModel();
|
|
||||||
|
|
||||||
initComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initComponents() {
|
|
||||||
|
|
||||||
showLocalePanel = new BoxPanel(BoxPanel.HORIZONTAL);
|
|
||||||
final Label showLocaleLabel = new Label(new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
final Label target = (Label) event.getTarget();
|
|
||||||
if (selectedAssetId == null) {
|
|
||||||
target.setLabel(new GlobalizedMessage(
|
|
||||||
"cms.ui.asset.initial_locale",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
} else {
|
|
||||||
target.setLabel(new GlobalizedMessage(
|
|
||||||
"cms.ui.asset.show_locale",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
showLocaleSelect = new SingleSelect("selected-locale");
|
|
||||||
try {
|
|
||||||
showLocaleSelect.addPrintListener(new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
if (selectedAssetId == null) {
|
|
||||||
final SingleSelect target = (SingleSelect) event
|
|
||||||
.getTarget();
|
|
||||||
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
final List<String> langs = new ArrayList<>(
|
|
||||||
KernelConfig.getConfig().getSupportedLanguages());
|
|
||||||
langs.sort((lang1, lang2) -> lang1.compareTo(lang2));
|
|
||||||
|
|
||||||
langs.forEach(lang -> {
|
|
||||||
target.addOption(new Option(lang, new Text(lang)));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
final SingleSelect target = (SingleSelect) event
|
|
||||||
.getTarget();
|
|
||||||
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
final List<Locale> availableLocales = getController()
|
|
||||||
.availableLocales(selectedAssetId,
|
|
||||||
getAssetClass());
|
|
||||||
availableLocales.sort((locale1, locale2) -> {
|
|
||||||
return locale1.toString().compareTo(locale2
|
|
||||||
.toString());
|
|
||||||
});
|
|
||||||
availableLocales.forEach(locale -> target.addOption(
|
|
||||||
new Option(locale.toString(),
|
|
||||||
new Text(locale.toString()))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (TooManyListenersException ex) {
|
|
||||||
throw new UnexpectedErrorException(ex);
|
|
||||||
}
|
|
||||||
showLocaleSubmit = new Submit(new GlobalizedMessage(
|
|
||||||
"cms.ui.asset.show_locale",
|
|
||||||
CmsConstants.CMS_BUNDLE)) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible(final PageState state) {
|
|
||||||
return getSelectedAssetId(state) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
showLocalePanel.add(showLocaleLabel);
|
|
||||||
showLocalePanel.add(showLocaleSelect);
|
|
||||||
showLocalePanel.add(showLocaleSubmit);
|
|
||||||
add(showLocalePanel);
|
|
||||||
|
|
||||||
addLocalePanel = new BoxPanel(BoxPanel.HORIZONTAL) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible(final PageState state) {
|
|
||||||
return getSelectedAssetId(state) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
final Label addLocaleLabel = new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.asset.add_locale",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
addLocaleSelect = new SingleSelect("add-locale-select");
|
|
||||||
try {
|
|
||||||
addLocaleSelect.addPrintListener(new PrintListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
if (selectedAssetId != null) {
|
|
||||||
final SingleSelect target = (SingleSelect) event
|
|
||||||
.getTarget();
|
|
||||||
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
final List<Locale> creatableLocales = getController()
|
|
||||||
.creatableLocales(selectedAssetId,
|
|
||||||
getAssetClass());
|
|
||||||
creatableLocales.sort((locale1, locale2) -> {
|
|
||||||
return locale1
|
|
||||||
.toString()
|
|
||||||
.compareTo(locale2.toString());
|
|
||||||
});
|
|
||||||
creatableLocales.forEach(locale -> target.addOption(
|
|
||||||
new Option(locale.toString(),
|
|
||||||
new Text(locale.toString()))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (TooManyListenersException ex) {
|
|
||||||
throw new UnexpectedErrorException(ex);
|
|
||||||
}
|
|
||||||
addLocaleSubmit = new Submit(new GlobalizedMessage(
|
|
||||||
"cms.ui.asset.add_locale",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
addLocalePanel.add(addLocaleLabel);
|
|
||||||
addLocalePanel.add(addLocaleSelect);
|
|
||||||
addLocalePanel.add(addLocaleSubmit);
|
|
||||||
add(addLocalePanel);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage("cms.ui.asset.name",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
name = new TextField(ASSET_NAME);
|
|
||||||
add(name);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage("cms.ui.asset.title",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
title = new TextField(ASSET_TITLE);
|
|
||||||
add(title);
|
|
||||||
|
|
||||||
addWidgets();
|
|
||||||
|
|
||||||
saveCancelSection = new SaveCancelSection();
|
|
||||||
add(saveCancelSection);
|
|
||||||
|
|
||||||
addInitListener(this);
|
|
||||||
addProcessListener(this);
|
|
||||||
addSubmissionListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addWidgets() {
|
|
||||||
//Nothing here
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getTitle(final PageState state) {
|
|
||||||
return (String) title.getValue(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Long getSelectedAssetId(final PageState state) {
|
|
||||||
|
|
||||||
final Object key = selectionModel.getSelectedKey(state);
|
|
||||||
if (key == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return (Long) key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(final FormSectionEvent event) throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
final Map<String, Object> data;
|
|
||||||
if (selectedAssetId == null) {
|
|
||||||
showLocaleSelect.setValue(state,
|
|
||||||
KernelConfig
|
|
||||||
.getConfig()
|
|
||||||
.getDefaultLocale()
|
|
||||||
.toString());
|
|
||||||
|
|
||||||
data = Collections.emptyMap();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
showLocaleSelect.setValue(state,
|
|
||||||
getSelectedLocale(state));
|
|
||||||
|
|
||||||
data = getController().getAssetData(selectedAssetId,
|
|
||||||
getAssetClass(),
|
|
||||||
getSelectedLocale(state));
|
|
||||||
|
|
||||||
name.setValue(state,
|
|
||||||
data.get(AbstractAssetFormController.DISPLAY_NAME));
|
|
||||||
title.setValue(state,
|
|
||||||
data.get(AbstractAssetFormController.TITLE));
|
|
||||||
}
|
|
||||||
|
|
||||||
initForm(state, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Locale getSelectedLocale(final PageState state) {
|
|
||||||
|
|
||||||
final Object selected = showLocaleSelect.getValue(state);
|
|
||||||
if (selected == null) {
|
|
||||||
return KernelConfig.getConfig().getDefaultLocale();
|
|
||||||
} else if (selected instanceof Locale) {
|
|
||||||
return (Locale) selected;
|
|
||||||
} else if (selected instanceof String) {
|
|
||||||
return new Locale((String) selected);
|
|
||||||
} else {
|
|
||||||
return new Locale(selected.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getTitleValue(final PageState state) {
|
|
||||||
return (String) title.getValue(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
|
|
||||||
name.setValue(state,
|
|
||||||
data.get(AbstractAssetFormController.DISPLAY_NAME));
|
|
||||||
|
|
||||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
// @SuppressWarnings("unchecked")
|
|
||||||
// final AbstractAssetFormController<T> controller = cdiUtil
|
|
||||||
// .findBean(AbstractAssetFormController.class);
|
|
||||||
title.setValue(state,
|
|
||||||
data.get(AbstractAssetFormController.TITLE));
|
|
||||||
showLocale(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
if (showLocaleSubmit.isSelected(state)) {
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
initForm(state,
|
|
||||||
getController().getAssetData(selectedAssetId,
|
|
||||||
getAssetClass(),
|
|
||||||
getSelectedLocale(state)));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addLocaleSubmit.isSelected(state)) {
|
|
||||||
final Locale add = new Locale((String) addLocaleSelect
|
|
||||||
.getValue(state));
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
getController().addLocale(selectedAssetId, add, getAssetClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
data.put(AbstractAssetFormController.DISPLAY_NAME,
|
|
||||||
name.getValue(state));
|
|
||||||
data.put(AbstractAssetFormController.TITLE,
|
|
||||||
title.getValue(state));
|
|
||||||
data.putAll(collectData(event));
|
|
||||||
|
|
||||||
final Long selectedAssetId;
|
|
||||||
if (getSelectedAssetId(state) == null) {
|
|
||||||
|
|
||||||
selectedAssetId = getController()
|
|
||||||
.createAsset(assetPane
|
|
||||||
.getFolderSelectionModel()
|
|
||||||
.getSelectedObject(state),
|
|
||||||
getSelectedLocale(state),
|
|
||||||
getAssetClass(),
|
|
||||||
data);
|
|
||||||
} else {
|
|
||||||
selectedAssetId = getSelectedAssetId(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
getController().updateAsset(selectedAssetId,
|
|
||||||
getSelectedLocale(state),
|
|
||||||
getAssetClass(),
|
|
||||||
data);
|
|
||||||
|
|
||||||
assetPane.browseMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Class<T> getAssetClass();
|
|
||||||
|
|
||||||
protected abstract void showLocale(final PageState state);
|
|
||||||
|
|
||||||
protected abstract Map<String, Object> collectData(
|
|
||||||
final FormSectionEvent event)
|
|
||||||
throws FormProcessException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void submitted(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (saveCancelSection.getCancelButton().isSelected(state)) {
|
|
||||||
selectionModel.clearSelection(state);
|
|
||||||
assetPane.browseMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AssetFormController<T> getController() {
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final AssetFormControllers controllers = cdiUtil
|
|
||||||
.findBean(AssetFormControllers.class);
|
|
||||||
|
|
||||||
return controllers.findController(getAssetClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,263 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import org.librecms.assets.AssetL10NManager;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
import org.librecms.contentsection.AssetManager;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An base class for implementations of {@link AssetFormController}.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractAssetFormController<T extends Asset> implements
|
|
||||||
AssetFormController<T> {
|
|
||||||
|
|
||||||
protected static final String DISPLAY_NAME = "displayName";
|
|
||||||
protected static final String TITLE = "title";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetManager assetManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetL10NManager l10nManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the basic data of the provided asset. Subclasses should not
|
|
||||||
* overrride this method. Instead they should provided an implementation of
|
|
||||||
* {@link #getAssetData(org.librecms.contentsection.Asset, java.util.Locale)}.
|
|
||||||
*
|
|
||||||
* @param assetType The {@link Asset} from which the data is read.
|
|
||||||
* @param selectedLocale The locale for which the data is read.
|
|
||||||
*
|
|
||||||
* @return A map with the data of the basic properties of the provided
|
|
||||||
* asset.
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getAssetData(final Long assetId,
|
|
||||||
final Class<T> assetType,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(assetId, "Can't get data from asset null.");
|
|
||||||
Objects.requireNonNull(selectedLocale,
|
|
||||||
"Can't get data from asset for locale null.");
|
|
||||||
|
|
||||||
final T asset = loadAsset(assetId, assetType);
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
|
|
||||||
data.put(DISPLAY_NAME, asset.getDisplayName());
|
|
||||||
data.put(TITLE, asset.getTitle().getValue(selectedLocale));
|
|
||||||
|
|
||||||
data.putAll(getAssetData(asset, selectedLocale));
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Map<String, Object> getAssetData(
|
|
||||||
final T asset, final Locale selectedLocale);
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public long createAsset(final Folder infolder,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Class<T> assetType,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
if (!data.containsKey(DISPLAY_NAME)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"data does not contain a value for displayName.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data.containsKey(TITLE)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"data does not contain a value for title.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final String name = (String) data.get(DISPLAY_NAME);
|
|
||||||
final String title = (String) data.get(TITLE);
|
|
||||||
|
|
||||||
final T asset = assetManager
|
|
||||||
.createAsset(name,
|
|
||||||
title,
|
|
||||||
selectedLocale,
|
|
||||||
infolder,
|
|
||||||
assetType);
|
|
||||||
|
|
||||||
return asset.getObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the provided asset with the provided data.
|
|
||||||
*
|
|
||||||
* This method is not intended to be overridden, but can't be {@code final}
|
|
||||||
* because of limitations of CDI. To update type specific properties
|
|
||||||
* implement
|
|
||||||
* {@link #updateAssetProperties(org.librecms.contentsection.Asset, java.util.Locale, java.util.Map)}.
|
|
||||||
*
|
|
||||||
* This method calls
|
|
||||||
* {@link AssetRepository#save(org.librecms.contentsection.Asset)} after the
|
|
||||||
* properties are set to save the changes to the database.
|
|
||||||
*
|
|
||||||
* @param assetId The ID of the asset to update.
|
|
||||||
* @param selectedLocale The locale for which the asset is updated.
|
|
||||||
* @param data The data used to update the asset.
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public void updateAsset(final Long assetId,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Class<T> assetType,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(selectedLocale,
|
|
||||||
"Can't get update asset for locale null.");
|
|
||||||
Objects.requireNonNull(data, "Can't update asset without data.");
|
|
||||||
|
|
||||||
final T asset = loadAsset(assetId, assetType);
|
|
||||||
if (data.containsKey(DISPLAY_NAME)) {
|
|
||||||
asset.setDisplayName((String) data.get(DISPLAY_NAME));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(TITLE)) {
|
|
||||||
|
|
||||||
final String title = (String) data.get(TITLE);
|
|
||||||
asset.getTitle().putValue(selectedLocale, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAssetProperties(asset, selectedLocale, data);
|
|
||||||
|
|
||||||
assetRepository.save(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override this method to process data for type specific properties.
|
|
||||||
*
|
|
||||||
* This method is called by
|
|
||||||
* {@link #updateAsset(org.librecms.contentsection.Asset, java.util.Locale, java.util.Map)}.
|
|
||||||
* Implementations should <strong>not</strong> call
|
|
||||||
* {@link AssetRepository#save}. Saving the update asset is done by
|
|
||||||
* {@link #updateAsset(org.librecms.contentsection.Asset, java.util.Locale, java.util.Map)}.
|
|
||||||
*
|
|
||||||
* An implementation should not assume that a value for each property is
|
|
||||||
* present in the provided map. Instead the overriding method should check
|
|
||||||
* if a value for a property is available by using
|
|
||||||
* {@link Map#containsKey(java.lang.Object)} first.
|
|
||||||
*
|
|
||||||
* @param asset The asset to update.
|
|
||||||
* @param selectedLocale The locale for which the asset is updated.
|
|
||||||
* @param data The data used to update the asset.
|
|
||||||
*/
|
|
||||||
public abstract void updateAssetProperties(final T asset,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Map<String, Object> data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines for which locales the provided asset has data.
|
|
||||||
*
|
|
||||||
* @param assetId The asset.
|
|
||||||
*
|
|
||||||
* @return A list of all locales for which the asset has data.
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public List<Locale> availableLocales(final Long assetId,
|
|
||||||
final Class<T> assetType) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(
|
|
||||||
assetId,
|
|
||||||
"Can't get available locales for asset with ID null.");
|
|
||||||
|
|
||||||
final T selectedAsset = loadAsset(assetId, assetType);
|
|
||||||
|
|
||||||
return new ArrayList<>(l10nManager.availableLocales(selectedAsset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines for locales the asset has no data yet.
|
|
||||||
*
|
|
||||||
* @param assetId The asset.
|
|
||||||
*
|
|
||||||
* @return A list of all locales for which the provided asset has no data
|
|
||||||
* yet.
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public List<Locale> creatableLocales(final Long assetId,
|
|
||||||
final Class<T> assetType) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(
|
|
||||||
assetId,
|
|
||||||
"Can't get creatable locales for asset with ID null.");
|
|
||||||
|
|
||||||
final T selectedAsset = loadAsset(assetId, assetType);
|
|
||||||
|
|
||||||
return new ArrayList<>(l10nManager.creatableLocales(selectedAsset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
public void addLocale(final Long assetId,
|
|
||||||
final Locale locale,
|
|
||||||
final Class<T> assetType) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(assetId, "Can't add a locale to asset null.");
|
|
||||||
Objects.requireNonNull(locale, "Can't add locale null to an asset.");
|
|
||||||
|
|
||||||
final T selectedAsset = loadAsset(assetId, assetType);
|
|
||||||
|
|
||||||
l10nManager.addLanguage(selectedAsset, locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param assetId
|
|
||||||
* @param assetType
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected T loadAsset(final Long assetId, final Class<T> assetType) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(assetId, "null is not a valid assetId");
|
|
||||||
|
|
||||||
return assetRepository
|
|
||||||
.findById(assetId, assetType)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No asset with ID %d found.", assetId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,446 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.ControlLink;
|
|
||||||
import com.arsdigita.bebop.Image;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.Page;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Paginator;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.SingleSelectionModel;
|
|
||||||
import com.arsdigita.bebop.Table;
|
|
||||||
import com.arsdigita.bebop.Text;
|
|
||||||
import com.arsdigita.bebop.event.TableActionAdapter;
|
|
||||||
import com.arsdigita.bebop.event.TableActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.TableActionListener;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
|
|
||||||
import com.arsdigita.bebop.table.DefaultTableColumnModel;
|
|
||||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
|
||||||
import com.arsdigita.bebop.table.TableColumn;
|
|
||||||
import com.arsdigita.bebop.table.TableHeader;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
|
||||||
|
|
||||||
import static org.librecms.CmsConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Browse folder and assets.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class AssetFolderBrowser extends Table {
|
|
||||||
|
|
||||||
protected static final String SORT_ACTION_UP = "sortActionUp";
|
|
||||||
protected static final String SORT_ACTION_DOWN = "sortActionDown";
|
|
||||||
protected final static String SORT_KEY_NAME = "name";
|
|
||||||
protected final static String SORT_KEY_TITLE = "title";
|
|
||||||
protected final static String SORT_KEY_TYPE = "type";
|
|
||||||
protected final static String SORT_KEY_LAST_MODIFIED_DATE = "lastModified";
|
|
||||||
protected final static String SORT_KEY_CREATION_DATE = "creationDate";
|
|
||||||
|
|
||||||
private final AssetPane assetPane;
|
|
||||||
private TableActionListener folderChanger;
|
|
||||||
private TableActionListener folderDeleter;
|
|
||||||
private TableColumn nameColumn;
|
|
||||||
private TableColumn deleteColumn;
|
|
||||||
private final StringParameter sortTypeParameter = new StringParameter(
|
|
||||||
"sortType");
|
|
||||||
private final StringParameter sortDirectionParameter = new StringParameter(
|
|
||||||
"sortDir");
|
|
||||||
|
|
||||||
private Paginator paginator;
|
|
||||||
private long folderSize;
|
|
||||||
|
|
||||||
public AssetFolderBrowser(final AssetPane assetPane) {
|
|
||||||
super();
|
|
||||||
sortTypeParameter.setDefaultValue(SORT_KEY_NAME);
|
|
||||||
sortDirectionParameter.setDefaultValue(SORT_ACTION_UP);
|
|
||||||
|
|
||||||
this.assetPane = assetPane;
|
|
||||||
|
|
||||||
initComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initComponents() {
|
|
||||||
|
|
||||||
final GlobalizedMessage[] headers = {
|
|
||||||
new GlobalizedMessage("cms.ui.folder.name",
|
|
||||||
CMS_FOLDER_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.folder.title",
|
|
||||||
CMS_FOLDER_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.folder.type",
|
|
||||||
CMS_FOLDER_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.asset.thumbnail",
|
|
||||||
CMS_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.folder.creation_date",
|
|
||||||
CMS_FOLDER_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.folder.last_modified",
|
|
||||||
CMS_FOLDER_BUNDLE),
|
|
||||||
new GlobalizedMessage("cms.ui.folder.action",
|
|
||||||
CMS_FOLDER_BUNDLE)};
|
|
||||||
|
|
||||||
setModelBuilder(new AssetFolderBrowserTableModelBuilder());
|
|
||||||
setColumnModel(new DefaultTableColumnModel(headers));
|
|
||||||
setHeader(new TableHeader(getColumnModel()));
|
|
||||||
setClassAttr("dataTable");
|
|
||||||
|
|
||||||
getHeader().setDefaultRenderer(
|
|
||||||
new com.arsdigita.cms.ui.util.DefaultTableCellRenderer());
|
|
||||||
|
|
||||||
nameColumn = getColumn(AssetFolderBrowserTableModel.COL_NAME);
|
|
||||||
nameColumn.setCellRenderer(new NameCellRenderer());
|
|
||||||
nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
|
|
||||||
|
|
||||||
getColumn(AssetFolderBrowserTableModel.COL_THUMBNAIL)
|
|
||||||
.setCellRenderer(new ThumbnailCellRenderer());
|
|
||||||
|
|
||||||
getColumn(AssetFolderBrowserTableModel.COL_CREATION_DATE)
|
|
||||||
.setHeaderRenderer(
|
|
||||||
new HeaderCellRenderer(SORT_KEY_CREATION_DATE));
|
|
||||||
getColumn(AssetFolderBrowserTableModel.COL_CREATION_DATE)
|
|
||||||
.setCellRenderer(new DateCellRenderer());
|
|
||||||
|
|
||||||
getColumn(AssetFolderBrowserTableModel.COL_LAST_MODIFIED)
|
|
||||||
.setHeaderRenderer(new HeaderCellRenderer(
|
|
||||||
SORT_KEY_LAST_MODIFIED_DATE));
|
|
||||||
getColumn(AssetFolderBrowserTableModel.COL_LAST_MODIFIED)
|
|
||||||
.setCellRenderer(new DateCellRenderer());
|
|
||||||
|
|
||||||
deleteColumn = getColumn(AssetFolderBrowserTableModel.COL_DELETEABLE);
|
|
||||||
deleteColumn.setCellRenderer(new ActionCellRenderer());
|
|
||||||
deleteColumn.setAlign("center");
|
|
||||||
|
|
||||||
folderChanger = new FolderChanger();
|
|
||||||
addTableActionListener(folderChanger);
|
|
||||||
|
|
||||||
folderDeleter = new ItemDeleter();
|
|
||||||
addTableActionListener(folderDeleter);
|
|
||||||
|
|
||||||
setEmptyView(new Label(new GlobalizedMessage("cms.ui.folder.no_assets",
|
|
||||||
CMS_FOLDER_BUNDLE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(final Page page) {
|
|
||||||
|
|
||||||
super.register(page);
|
|
||||||
|
|
||||||
page.addComponentStateParam(
|
|
||||||
this,
|
|
||||||
getFolderSelectionModel().getStateParameter());
|
|
||||||
page.addComponentStateParam(this, sortTypeParameter);
|
|
||||||
page.addComponentStateParam(this, sortDirectionParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected FolderSelectionModel getFolderSelectionModel() {
|
|
||||||
return assetPane.getFolderSelectionModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SingleSelectionModel<Long> getSelectedAssetModel() {
|
|
||||||
return assetPane.getSelectedAssetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Paginator getPaginator() {
|
|
||||||
return paginator;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setPaginator(final Paginator paginator) {
|
|
||||||
this.paginator = paginator;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getSortType(final PageState state) {
|
|
||||||
return (String) state.getValue(sortTypeParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getSortDirection(final PageState state) {
|
|
||||||
return (String) state.getValue(sortDirectionParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HeaderCellRenderer extends DefaultTableCellRenderer {
|
|
||||||
|
|
||||||
private final String headerKey;
|
|
||||||
|
|
||||||
public HeaderCellRenderer(final String headerKey) {
|
|
||||||
super(true);
|
|
||||||
this.headerKey = headerKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
|
|
||||||
final GlobalizedMessage headerName = (GlobalizedMessage) value;
|
|
||||||
final String sortKey = (String) state.getValue(sortTypeParameter);
|
|
||||||
final boolean isCurrentKey = sortKey.equals(key);
|
|
||||||
final String currentSortDirection = (String) state
|
|
||||||
.getValue(sortDirectionParameter);
|
|
||||||
final String imageUrlStub;
|
|
||||||
|
|
||||||
if (SORT_ACTION_UP.equals(currentSortDirection)) {
|
|
||||||
imageUrlStub = "gray-triangle-up.gif";
|
|
||||||
} else {
|
|
||||||
imageUrlStub = "gray-triangle-down.gif";
|
|
||||||
}
|
|
||||||
|
|
||||||
final ControlLink link = new ControlLink(new Label(headerName)) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setControlEvent(final PageState state) {
|
|
||||||
String sortDirectionAction;
|
|
||||||
// by default, everything sorts "up" unless it
|
|
||||||
// is the current key and it is already pointing up
|
|
||||||
if (SORT_ACTION_UP.equals(currentSortDirection)
|
|
||||||
&& isCurrentKey) {
|
|
||||||
sortDirectionAction = SORT_ACTION_DOWN;
|
|
||||||
} else {
|
|
||||||
sortDirectionAction = SORT_ACTION_UP;
|
|
||||||
}
|
|
||||||
state.setControlEvent(table,
|
|
||||||
sortDirectionAction,
|
|
||||||
headerKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
final Label label = new Label();
|
|
||||||
label.setLabel(headerName);
|
|
||||||
label.setClassAttr("folderBrowserLink");
|
|
||||||
label.setOutputEscaping(false);
|
|
||||||
label.setFontWeight(Label.BOLD);
|
|
||||||
|
|
||||||
final SimpleContainer container = new SimpleContainer();
|
|
||||||
container.add(label);
|
|
||||||
if (isCurrentKey) {
|
|
||||||
Image image = new Image("/assets/" + imageUrlStub);
|
|
||||||
image.setBorder("0");
|
|
||||||
container.add(image);
|
|
||||||
}
|
|
||||||
link.setChild(container);
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Produce links to view an item or control links for folders to change into
|
|
||||||
* the folder.
|
|
||||||
*/
|
|
||||||
private class NameCellRenderer extends DefaultTableCellRenderer {
|
|
||||||
|
|
||||||
public NameCellRenderer() {
|
|
||||||
super(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
|
|
||||||
final String name = (String) value;
|
|
||||||
final ContentSection section = CMS.getContext().
|
|
||||||
getContentSection();
|
|
||||||
final ContentSectionManager sectionManager = CdiUtil.
|
|
||||||
createCdiUtil()
|
|
||||||
.findBean(ContentSectionManager.class);
|
|
||||||
|
|
||||||
final boolean isFolder = ((AssetFolderBrowserTableModel) table
|
|
||||||
.getTableModel(state))
|
|
||||||
.isFolder();
|
|
||||||
final long objectId = getObjectId(key);
|
|
||||||
|
|
||||||
if (isFolder) {
|
|
||||||
//return new ControlLink(new Text(name));
|
|
||||||
return super.getComponent(table,
|
|
||||||
state,
|
|
||||||
value,
|
|
||||||
isSelected,
|
|
||||||
objectId,
|
|
||||||
row,
|
|
||||||
column);
|
|
||||||
} else {
|
|
||||||
return new ControlLink(new Text(name));
|
|
||||||
|
|
||||||
// return new Link(new Text(name),
|
|
||||||
// itemResolver.generateItemURL(state,
|
|
||||||
// objectId,
|
|
||||||
// name,
|
|
||||||
// section,
|
|
||||||
// "DRAFT"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ThumbnailCellRenderer implements TableCellRenderer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
if (value == null) {
|
|
||||||
return new Text("");
|
|
||||||
} else {
|
|
||||||
final Image image = new Image((String) value, "");
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DateCellRenderer implements TableCellRenderer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
if (value instanceof Date) {
|
|
||||||
final Date date = (Date) value;
|
|
||||||
return new Text(String.format("%1$TF %1$TT", date));
|
|
||||||
} else if (value == null) {
|
|
||||||
return new Text("");
|
|
||||||
} else {
|
|
||||||
return new Text(value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Produce delete links for items and non-empty folders.
|
|
||||||
*/
|
|
||||||
private class ActionCellRenderer implements TableCellRenderer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
if ((!(Boolean) value)) {
|
|
||||||
return new Label(" ", false);
|
|
||||||
} else {
|
|
||||||
final ControlLink link = new ControlLink(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.folder.delete",
|
|
||||||
CmsConstants.CMS_FOLDER_BUNDLE)));
|
|
||||||
link.setConfirmation(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.folder.delete_confirmation_assets",
|
|
||||||
CmsConstants.CMS_FOLDER_BUNDLE));
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deletes an item
|
|
||||||
private class ItemDeleter extends TableActionAdapter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cellSelected(final TableActionEvent event) {
|
|
||||||
int col = event.getColumn();
|
|
||||||
|
|
||||||
if (deleteColumn != getColumn(col)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final AssetFolderBrowserController controller = cdiUtil.findBean(
|
|
||||||
AssetFolderBrowserController.class);
|
|
||||||
controller.deleteObject((String) event.getRowKey());
|
|
||||||
|
|
||||||
((Table) event.getSource()).clearSelection(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FolderChanger extends TableActionAdapter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cellSelected(final TableActionEvent event) {
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final int col = event.getColumn();
|
|
||||||
|
|
||||||
if (nameColumn != getColumn(col)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearSelection(state);
|
|
||||||
final String rowKey = (String) event.getRowKey();
|
|
||||||
if (rowKey.startsWith(CmsConstants.FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
|
|
||||||
getFolderSelectionModel().setSelectedKey(state,
|
|
||||||
getObjectId(rowKey));
|
|
||||||
} else if (rowKey.startsWith(
|
|
||||||
CmsConstants.FOLDER_BROWSER_KEY_PREFIX_ASSET)) {
|
|
||||||
getSelectedAssetModel().setSelectedKey(state,
|
|
||||||
getObjectId(rowKey));
|
|
||||||
assetPane.editAssetMode(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getObjectId(final Object key) {
|
|
||||||
|
|
||||||
final String keyStr = (String) key;
|
|
||||||
|
|
||||||
if (keyStr.startsWith("folder-")) {
|
|
||||||
return Long.parseLong(keyStr.substring("folder-".length()));
|
|
||||||
} else if (keyStr.startsWith("asset-")) {
|
|
||||||
return Long.parseLong(keyStr.substring("asset-".length()));
|
|
||||||
} else {
|
|
||||||
return Long.parseLong(keyStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,638 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
|
||||||
import com.arsdigita.web.CCMDispatcherServlet;
|
|
||||||
|
|
||||||
import org.libreccm.categorization.Category;
|
|
||||||
import org.libreccm.categorization.CategoryManager;
|
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.AssetTypeInfo;
|
|
||||||
import org.librecms.assets.AssetTypesManager;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.TypedQuery;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Join;
|
|
||||||
import javax.persistence.criteria.Order;
|
|
||||||
import javax.persistence.criteria.Path;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
import org.libreccm.core.CcmObject;
|
|
||||||
import org.librecms.contentsection.AssetManager;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
import org.librecms.contentsection.FolderManager;
|
|
||||||
import org.librecms.contentsection.FolderRepository;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.librecms.assets.Image;
|
|
||||||
|
|
||||||
import static org.librecms.CmsConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
public class AssetFolderBrowserController {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager
|
|
||||||
.getLogger(AssetFolderBrowserController.class);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ConfigurationManager confManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private CategoryManager categoryManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetTypesManager typesManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private FolderRepository folderRepo;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private FolderManager folderManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepo;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetManager assetManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private GlobalizationHelper globalizationHelper;
|
|
||||||
|
|
||||||
private Locale defaultLocale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialisation method called by the CDI-Container after an instance of
|
|
||||||
* this class has be created by the container. Sets the
|
|
||||||
* {@link #defaultLocale} property using the the value from the
|
|
||||||
* {@link KernelConfig}.
|
|
||||||
*/
|
|
||||||
@PostConstruct
|
|
||||||
private void init() {
|
|
||||||
final KernelConfig kernelConfig = confManager.findConfiguration(
|
|
||||||
KernelConfig.class);
|
|
||||||
defaultLocale = kernelConfig.getDefaultLocale();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
List<AssetFolderBrowserTableRow> getAssetRows(final Folder folder,
|
|
||||||
final String orderBy,
|
|
||||||
final String orderDirection,
|
|
||||||
final int firstResult,
|
|
||||||
final int maxResults) {
|
|
||||||
final List<Folder> subFolders = findSubFolders(folder,
|
|
||||||
"%",
|
|
||||||
orderBy,
|
|
||||||
orderDirection,
|
|
||||||
firstResult,
|
|
||||||
maxResults);
|
|
||||||
final List<AssetFolderBrowserTableRow> subFolderRows = subFolders
|
|
||||||
.stream()
|
|
||||||
.map(subFolder -> buildRow(subFolder))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (subFolders.size() > maxResults) {
|
|
||||||
return subFolderRows;
|
|
||||||
} else {
|
|
||||||
final int maxAssets = maxResults - subFolders.size();
|
|
||||||
final int firstAsset = firstResult - subFolders.size();
|
|
||||||
|
|
||||||
final List<Asset> assets = findAssetsInFolder(folder,
|
|
||||||
"%",
|
|
||||||
orderBy,
|
|
||||||
orderDirection,
|
|
||||||
firstAsset,
|
|
||||||
maxAssets);
|
|
||||||
final List<AssetFolderBrowserTableRow> assetRows = assets
|
|
||||||
.stream()
|
|
||||||
.map(asset -> buildRow(asset))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<AssetFolderBrowserTableRow> rows = new ArrayList<>();
|
|
||||||
rows.addAll(subFolderRows);
|
|
||||||
rows.addAll(assetRows);
|
|
||||||
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected long countObjects(final Folder folder) {
|
|
||||||
|
|
||||||
return countObjects(folder, "%");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected long countObjects(final Folder folder, final String filterTerm) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(folder);
|
|
||||||
Objects.requireNonNull(filterTerm);
|
|
||||||
|
|
||||||
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
|
|
||||||
final Root<CcmObject> from = criteriaQuery.from(CcmObject.class);
|
|
||||||
|
|
||||||
criteriaQuery = criteriaQuery.select(builder.count(from));
|
|
||||||
|
|
||||||
final List<Folder> subFolders = findSubFolders(
|
|
||||||
folder,
|
|
||||||
filterTerm,
|
|
||||||
AssetFolderBrowser.SORT_KEY_NAME,
|
|
||||||
AssetFolderBrowser.SORT_ACTION_UP,
|
|
||||||
-1,
|
|
||||||
-1);
|
|
||||||
final List<Asset> assets = findAssetsInFolder(
|
|
||||||
folder,
|
|
||||||
filterTerm,
|
|
||||||
AssetFolderBrowser.SORT_KEY_NAME,
|
|
||||||
AssetFolderBrowser.SORT_ACTION_UP,
|
|
||||||
-1,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
if (subFolders.isEmpty() && assets.isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
} else if (subFolders.isEmpty() && !assets.isEmpty()) {
|
|
||||||
criteriaQuery = criteriaQuery.where(from.in(assets));
|
|
||||||
} else if (!subFolders.isEmpty() && assets.isEmpty()) {
|
|
||||||
criteriaQuery = criteriaQuery.where(from.in(subFolders));
|
|
||||||
} else {
|
|
||||||
criteriaQuery = criteriaQuery.where(builder.or(
|
|
||||||
from.in(subFolders),
|
|
||||||
from.in(assets)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return entityManager.createQuery(criteriaQuery).getSingleResult();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected void copyObjects(final Folder targetFolder,
|
|
||||||
final String[] objectIds) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
Objects.requireNonNull(objectIds);
|
|
||||||
|
|
||||||
for (final String objectId : objectIds) {
|
|
||||||
if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
|
|
||||||
copyFolder(targetFolder,
|
|
||||||
Long.parseLong(objectId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
|
|
||||||
} else if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_ASSET)) {
|
|
||||||
copyAsset(targetFolder,
|
|
||||||
Long.parseLong(objectId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"ID '%s' does not start with '%s' or '%s'.",
|
|
||||||
objectId,
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_ASSET));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyFolder(final Folder targetFolder,
|
|
||||||
final long folderId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
|
|
||||||
final Folder folder = folderRepo.findById(folderId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No folder with ID %d in the database. "
|
|
||||||
+ "Where did that ID come from?",
|
|
||||||
folderId)));
|
|
||||||
|
|
||||||
folderManager.copyFolder(folder, targetFolder);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyAsset(final Folder targetFolder,
|
|
||||||
final long assetId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
|
|
||||||
final Asset asset = assetRepo
|
|
||||||
.findById(assetId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No asset ith ID %d in the database. Where did that ID come from?",
|
|
||||||
assetId)));
|
|
||||||
|
|
||||||
assetManager.copy(asset, targetFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public void moveObjects(final Folder targetFolder,
|
|
||||||
final String[] objectIds) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
Objects.requireNonNull(objectIds);
|
|
||||||
|
|
||||||
for (final String objectId : objectIds) {
|
|
||||||
if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
|
|
||||||
moveFolder(targetFolder,
|
|
||||||
Long.parseLong(objectId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
|
|
||||||
} else if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_ASSET)) {
|
|
||||||
moveAsset(targetFolder,
|
|
||||||
Long.parseLong(objectId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"ID '%s' does not start with '%s' or '%s'.",
|
|
||||||
objectId,
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_ASSET));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveFolder(final Folder targetFolder, final long folderId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
|
|
||||||
final Folder folder = folderRepo.findById(folderId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No folder with ID %d in the database. "
|
|
||||||
+ "Where did that ID come from?",
|
|
||||||
folderId)));
|
|
||||||
|
|
||||||
folderManager.moveFolder(folder, targetFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveAsset(final Folder targetFolder, final long assetId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(targetFolder);
|
|
||||||
|
|
||||||
final Asset asset = assetRepo
|
|
||||||
.findById(assetId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No asset with ID %d in the database. Where did that ID come from?",
|
|
||||||
assetId)));
|
|
||||||
|
|
||||||
assetManager.move(asset, targetFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected List<String> createInvalidTargetsList(final List<String> sources) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(sources);
|
|
||||||
|
|
||||||
final List<String> sourceFolderIds = sources
|
|
||||||
.stream()
|
|
||||||
.filter(source -> source.startsWith(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
final List<String> parentFolderIds = sourceFolderIds
|
|
||||||
.stream()
|
|
||||||
.map(sourceFolderId -> findParentFolderId(sourceFolderId))
|
|
||||||
.filter(Optional::isPresent)
|
|
||||||
.map(Optional::get)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
final List<List<String>> subFolderIds = sourceFolderIds
|
|
||||||
.stream()
|
|
||||||
.map(sourceFolderId -> findSubFolderIds(sourceFolderId))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> invalidTargetIds = new ArrayList<>();
|
|
||||||
invalidTargetIds.addAll(sourceFolderIds);
|
|
||||||
invalidTargetIds.addAll(parentFolderIds);
|
|
||||||
for (final List<String> subFolderIdList : subFolderIds) {
|
|
||||||
invalidTargetIds.addAll(subFolderIdList);
|
|
||||||
}
|
|
||||||
|
|
||||||
return invalidTargetIds;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<String> findParentFolderId(final String folderId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(folderId);
|
|
||||||
|
|
||||||
if (!folderId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"Provided string '%s' is not an ID of a folder.",
|
|
||||||
folderId));
|
|
||||||
}
|
|
||||||
|
|
||||||
final long objectId = Long.parseLong(folderId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
|
|
||||||
final Folder folder = folderRepo.findById(objectId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No folder with ID %d found in database. "
|
|
||||||
+ "Where did that ID come form?",
|
|
||||||
objectId)));
|
|
||||||
final Optional<Folder> parentFolder = folderManager.getParentFolder(
|
|
||||||
folder);
|
|
||||||
if (parentFolder.isPresent()) {
|
|
||||||
return Optional.empty();
|
|
||||||
} else {
|
|
||||||
return Optional.ofNullable(String.format(
|
|
||||||
"%s%d",
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
|
|
||||||
parentFolder.get().getObjectId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> findSubFolderIds(final String folderId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(folderId);
|
|
||||||
|
|
||||||
if (!folderId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"Provided string '%s' is not the ID of a folder.",
|
|
||||||
folderId));
|
|
||||||
}
|
|
||||||
|
|
||||||
final long objectId = Long.parseLong(folderId.substring(
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
|
|
||||||
final Folder folder = folderRepo.findById(objectId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No folder with ID %d found in database. "
|
|
||||||
+ "Where did that ID come form?",
|
|
||||||
objectId)));
|
|
||||||
return findSubFolders(folder)
|
|
||||||
.stream()
|
|
||||||
.map(subFolder -> String.format("%s%d",
|
|
||||||
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
|
|
||||||
subFolder.getObjectId()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Folder> findSubFolders(final Folder folder) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(folder);
|
|
||||||
|
|
||||||
if (folder.getSubFolders() == null
|
|
||||||
|| folder.getSubFolders().isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Folder> subFolders = new ArrayList<>();
|
|
||||||
for (final Folder subFolder : folder.getSubFolders()) {
|
|
||||||
subFolders.add(subFolder);
|
|
||||||
subFolders.addAll(findSubFolders(subFolder));
|
|
||||||
}
|
|
||||||
|
|
||||||
return subFolders;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the {@link AssetFolderBrowser} to delete an object.
|
|
||||||
*
|
|
||||||
* @param objectId
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected void deleteObject(final String objectId) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(objectId);
|
|
||||||
|
|
||||||
if (objectId.startsWith("folder-")) {
|
|
||||||
final long folderId = Long.parseLong(
|
|
||||||
objectId.substring("folder-".length()));
|
|
||||||
|
|
||||||
folderRepo
|
|
||||||
.findById(folderId)
|
|
||||||
.ifPresent(folderRepo::delete);
|
|
||||||
} else if (objectId.startsWith("asset-")) {
|
|
||||||
final long assetId = Long.parseLong(
|
|
||||||
objectId.substring("asset-".length()));
|
|
||||||
|
|
||||||
assetRepo
|
|
||||||
.findById(assetId)
|
|
||||||
.ifPresent(assetRepo::delete);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The objectId is expected to start with 'folder-' or 'asset-'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AssetFolderBrowserTableRow buildRow(final Folder folder) {
|
|
||||||
|
|
||||||
final AssetFolderBrowserTableRow row = new AssetFolderBrowserTableRow();
|
|
||||||
|
|
||||||
row.setObjectId(folder.getObjectId());
|
|
||||||
row.setObjectUuid(folder.getUuid());
|
|
||||||
row.setName(folder.getName());
|
|
||||||
if (folder.getTitle().hasValue(globalizationHelper
|
|
||||||
.getNegotiatedLocale())) {
|
|
||||||
row.setTitle(folder.getTitle().getValue(globalizationHelper
|
|
||||||
.getNegotiatedLocale()));
|
|
||||||
} else {
|
|
||||||
row.setTitle(folder.getTitle().getValue(defaultLocale));
|
|
||||||
}
|
|
||||||
row.setFolder(true);
|
|
||||||
row.setDeletable(!categoryManager.hasSubCategories(folder)
|
|
||||||
&& !categoryManager.hasObjects(folder));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
private AssetFolderBrowserTableRow buildRow(final Asset asset) {
|
|
||||||
|
|
||||||
final AssetFolderBrowserTableRow row = new AssetFolderBrowserTableRow();
|
|
||||||
|
|
||||||
row.setObjectId(asset.getObjectId());
|
|
||||||
row.setObjectUuid(asset.getUuid());
|
|
||||||
row.setName(asset.getDisplayName());
|
|
||||||
if (asset.getTitle().hasValue(globalizationHelper
|
|
||||||
.getNegotiatedLocale())) {
|
|
||||||
row.setTitle(asset.getTitle().getValue(globalizationHelper
|
|
||||||
.getNegotiatedLocale()));
|
|
||||||
} else {
|
|
||||||
row.setTitle(asset.getTitle().getValue(defaultLocale));
|
|
||||||
}
|
|
||||||
if (asset instanceof Image) {
|
|
||||||
row.setThumbnailUrl(String
|
|
||||||
.format("%s/content-sections/%s/images/"
|
|
||||||
+ "uuid-%s?width=150&height=100",
|
|
||||||
CCMDispatcherServlet.getContextPath(),
|
|
||||||
CMS.getContext().getContentSection().getLabel(),
|
|
||||||
asset.getUuid()));
|
|
||||||
}
|
|
||||||
final AssetTypeInfo typeInfo = typesManager
|
|
||||||
.getAssetTypeInfo(asset.getClass());
|
|
||||||
row.setTypeLabelBundle(typeInfo.getLabelBundle());
|
|
||||||
row.setTypeLabelKey(typeInfo.getLabelKey());
|
|
||||||
|
|
||||||
row.setFolder(false);
|
|
||||||
|
|
||||||
row.setDeletable(!assetManager.isAssetInUse(asset));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Folder> findSubFolders(final Folder folder,
|
|
||||||
final String filterTerm,
|
|
||||||
final String orderBy,
|
|
||||||
final String orderDirection,
|
|
||||||
final int firstResult,
|
|
||||||
final int maxResults) {
|
|
||||||
|
|
||||||
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
|
||||||
|
|
||||||
final CriteriaQuery<Folder> criteria = builder
|
|
||||||
.createQuery(Folder.class);
|
|
||||||
final Root<Folder> from = criteria.from(Folder.class);
|
|
||||||
|
|
||||||
final Order order;
|
|
||||||
if (AssetFolderBrowser.SORT_KEY_NAME.equals(orderBy)
|
|
||||||
&& AssetFolderBrowser.SORT_ACTION_DOWN.
|
|
||||||
equals(orderDirection)) {
|
|
||||||
order = builder.desc(from.get("name"));
|
|
||||||
} else {
|
|
||||||
order = builder.asc(from.get("name"));
|
|
||||||
}
|
|
||||||
|
|
||||||
final TypedQuery<Folder> query = entityManager
|
|
||||||
.createQuery(
|
|
||||||
criteria.where(
|
|
||||||
builder.and(
|
|
||||||
builder.
|
|
||||||
equal(from.get("parentCategory"),
|
|
||||||
folder),
|
|
||||||
builder.like(builder.lower(from.get(
|
|
||||||
"name")),
|
|
||||||
filterTerm)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.orderBy(order)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (firstResult >= 0) {
|
|
||||||
query.setFirstResult(firstResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxResults >= 0) {
|
|
||||||
query.setMaxResults(maxResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
return query.getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Asset> findAssetsInFolder(final Folder folder,
|
|
||||||
final String filterTerm,
|
|
||||||
final String orderBy,
|
|
||||||
final String orderDirection,
|
|
||||||
final int firstResult,
|
|
||||||
final int maxResults) {
|
|
||||||
|
|
||||||
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
|
||||||
|
|
||||||
final CriteriaQuery<Asset> criteria = builder.createQuery(Asset.class);
|
|
||||||
final Root<Asset> fromAsset = criteria.from(Asset.class);
|
|
||||||
final Join<Asset, Category> join = fromAsset.join("categories");
|
|
||||||
|
|
||||||
final Path<?> orderPath;
|
|
||||||
switch (orderBy) {
|
|
||||||
case AssetFolderBrowser.SORT_KEY_NAME:
|
|
||||||
orderPath = fromAsset.get("displayName");
|
|
||||||
break;
|
|
||||||
case AssetFolderBrowser.SORT_KEY_CREATION_DATE:
|
|
||||||
orderPath = fromAsset.get("creationDate");
|
|
||||||
break;
|
|
||||||
case AssetFolderBrowser.SORT_KEY_LAST_MODIFIED_DATE:
|
|
||||||
orderPath = fromAsset.get("lastModifed");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
orderPath = fromAsset.get("displayName");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Order order;
|
|
||||||
if (AssetFolderBrowser.SORT_ACTION_DOWN.equals(orderDirection)) {
|
|
||||||
order = builder.desc(orderPath);
|
|
||||||
} else {
|
|
||||||
order = builder.asc(orderPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.debug("The database contains {} assets.",
|
|
||||||
entityManager.createQuery(criteria.select(fromAsset)
|
|
||||||
.where(
|
|
||||||
builder.and(
|
|
||||||
builder.equal(join.get("category"),
|
|
||||||
folder),
|
|
||||||
builder.equal(join.get("type"),
|
|
||||||
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
|
|
||||||
builder.like(builder.lower(
|
|
||||||
fromAsset.get(
|
|
||||||
"displayName")),
|
|
||||||
filterTerm)
|
|
||||||
))).getResultList().size());
|
|
||||||
|
|
||||||
final TypedQuery<Asset> query = entityManager
|
|
||||||
.createQuery(
|
|
||||||
criteria.select(fromAsset)
|
|
||||||
.where(
|
|
||||||
builder.and(
|
|
||||||
builder.equal(join.get(
|
|
||||||
"category"), folder),
|
|
||||||
builder.equal(join.get("type"),
|
|
||||||
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
|
|
||||||
builder.like(builder.lower(
|
|
||||||
fromAsset.get(
|
|
||||||
"displayName")),
|
|
||||||
filterTerm)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.orderBy(order)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (firstResult >= 0) {
|
|
||||||
query.setFirstResult(firstResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxResults >= 0) {
|
|
||||||
query.setMaxResults(maxResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
return query.getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.PaginationModelBuilder;
|
|
||||||
import com.arsdigita.bebop.Paginator;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
class AssetFolderBrowserPaginationModelBuilder implements PaginationModelBuilder {
|
|
||||||
|
|
||||||
private final AssetFolderBrowser folderBrowser;
|
|
||||||
|
|
||||||
public AssetFolderBrowserPaginationModelBuilder(
|
|
||||||
final AssetFolderBrowser folderBrowser) {
|
|
||||||
|
|
||||||
this.folderBrowser = folderBrowser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getTotalSize(final Paginator paginator, final PageState state) {
|
|
||||||
|
|
||||||
final FolderSelectionModel folderSelectionModel = folderBrowser
|
|
||||||
.getFolderSelectionModel();
|
|
||||||
final Folder folder = folderSelectionModel.getSelectedObject(state);
|
|
||||||
if (folder == null) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final AssetFolderBrowserController controller = cdiUtil.findBean(
|
|
||||||
AssetFolderBrowserController.class);
|
|
||||||
return (int) controller.countObjects(folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible(final PageState state) {
|
|
||||||
return folderBrowser != null && folderBrowser.isVisible(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
class AssetFolderBrowserTableModel implements TableModel {
|
|
||||||
|
|
||||||
protected static final int COL_NAME = 0;
|
|
||||||
protected static final int COL_TITLE = 1;
|
|
||||||
protected static final int COL_TYPE = 2;
|
|
||||||
protected static final int COL_THUMBNAIL = 3;
|
|
||||||
protected static final int COL_CREATION_DATE = 4;
|
|
||||||
protected static final int COL_LAST_MODIFIED = 5;
|
|
||||||
protected static final int COL_DELETEABLE = 6;
|
|
||||||
|
|
||||||
private final Iterator<AssetFolderBrowserTableRow> iterator;
|
|
||||||
private AssetFolderBrowserTableRow currentRow;
|
|
||||||
|
|
||||||
public AssetFolderBrowserTableModel(
|
|
||||||
final List<AssetFolderBrowserTableRow> rows) {
|
|
||||||
|
|
||||||
iterator = rows.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColumnCount() {
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean nextRow() {
|
|
||||||
if (iterator.hasNext()) {
|
|
||||||
currentRow = iterator.next();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getElementAt(final int columnIndex) {
|
|
||||||
switch (columnIndex) {
|
|
||||||
case COL_NAME:
|
|
||||||
return currentRow.getName();
|
|
||||||
case COL_TITLE:
|
|
||||||
return currentRow.getTitle();
|
|
||||||
case COL_TYPE:
|
|
||||||
final String typeLabelBundle = currentRow.getTypeLabelBundle();
|
|
||||||
final String typeLabelKey = currentRow.getTypeLabelKey();
|
|
||||||
if (typeLabelKey == null) {
|
|
||||||
return new GlobalizedMessage("empty_text",
|
|
||||||
CmsConstants.CMS_BUNDLE);
|
|
||||||
} else {
|
|
||||||
return new GlobalizedMessage(typeLabelKey, typeLabelBundle);
|
|
||||||
}
|
|
||||||
case COL_THUMBNAIL:
|
|
||||||
return currentRow.getThumbnailUrl();
|
|
||||||
case COL_CREATION_DATE:
|
|
||||||
return currentRow.getCreated();
|
|
||||||
case COL_LAST_MODIFIED:
|
|
||||||
return currentRow.getLastModified();
|
|
||||||
case COL_DELETEABLE:
|
|
||||||
return currentRow.isDeletable();
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"Illegal column index %d.", columnIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getKeyAt(final int columnIndex) {
|
|
||||||
if (currentRow.isFolder()) {
|
|
||||||
return String.format("folder-%d", currentRow.getObjectId());
|
|
||||||
} else {
|
|
||||||
return String.format("asset-%d", currentRow.getObjectId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFolder() {
|
|
||||||
return currentRow.isFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Paginator;
|
|
||||||
import com.arsdigita.bebop.Table;
|
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
|
||||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
|
||||||
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
|
|
||||||
import com.arsdigita.util.LockableImpl;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the {@link TableModel} for the {@link AssetFolderBrowser}.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
class AssetFolderBrowserTableModelBuilder
|
|
||||||
extends LockableImpl
|
|
||||||
implements TableModelBuilder {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager
|
|
||||||
.getLogger(AssetFolderBrowserTableModelBuilder.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TableModel makeModel(final Table table,
|
|
||||||
final PageState state) {
|
|
||||||
|
|
||||||
if (!(table instanceof AssetFolderBrowser)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The AssetFolderBrowserTableModelBuilder can only be used "
|
|
||||||
+ "for the AssetFolderBrowser.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final AssetFolderBrowser assetFolderBrowser = (AssetFolderBrowser) table;
|
|
||||||
final FolderSelectionModel folderSelectionModel = assetFolderBrowser
|
|
||||||
.getFolderSelectionModel();
|
|
||||||
final Folder folder = folderSelectionModel.getSelectedObject(state);
|
|
||||||
if (folder == null) {
|
|
||||||
return Table.EMPTY_MODEL;
|
|
||||||
} else {
|
|
||||||
assetFolderBrowser.getRowSelectionModel().clearSelection(state);
|
|
||||||
final Paginator paginator = assetFolderBrowser.getPaginator();
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final AssetFolderBrowserController controller = cdiUtil
|
|
||||||
.findBean(AssetFolderBrowserController.class);
|
|
||||||
final String orderBy;
|
|
||||||
if (assetFolderBrowser.getSortType(state) == null) {
|
|
||||||
orderBy = AssetFolderBrowser.SORT_KEY_NAME;
|
|
||||||
} else {
|
|
||||||
orderBy = assetFolderBrowser.getSortType(state);
|
|
||||||
}
|
|
||||||
final String orderDirection;
|
|
||||||
if (assetFolderBrowser.getSortDirection(state) == null) {
|
|
||||||
orderDirection = AssetFolderBrowser.SORT_ACTION_UP;
|
|
||||||
} else {
|
|
||||||
orderDirection = assetFolderBrowser.getSortDirection(state);
|
|
||||||
}
|
|
||||||
final int first = paginator.getFirst(state);
|
|
||||||
final int pageSize = paginator.getPageSize(state);
|
|
||||||
|
|
||||||
final long start = System.nanoTime();
|
|
||||||
LOGGER.debug("Retrieving table rows...");
|
|
||||||
final List<AssetFolderBrowserTableRow> rows = controller
|
|
||||||
.getAssetRows(folder,
|
|
||||||
orderBy,
|
|
||||||
orderDirection,
|
|
||||||
first - 1,
|
|
||||||
pageSize);
|
|
||||||
|
|
||||||
LOGGER.debug("Retrieve table rows in {} ms.",
|
|
||||||
(System.nanoTime() - start) / 1000);
|
|
||||||
return new AssetFolderBrowserTableModel(rows);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
class AssetFolderBrowserTableRow {
|
|
||||||
|
|
||||||
private long objectId;
|
|
||||||
private String objectUuid;
|
|
||||||
private String name;
|
|
||||||
private String title;
|
|
||||||
private String thumbnailUrl;
|
|
||||||
private String typeLabelBundle;
|
|
||||||
private String typeLabelKey;
|
|
||||||
private Date created;
|
|
||||||
private Date lastModified;
|
|
||||||
private boolean deletable;
|
|
||||||
private boolean folder;
|
|
||||||
|
|
||||||
public long getObjectId() {
|
|
||||||
return objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setObjectId(final long objectId) {
|
|
||||||
this.objectId = objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getObjectUuid() {
|
|
||||||
return objectUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setObjectUuid(final String objectUuid) {
|
|
||||||
this.objectUuid = objectUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(final String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(final String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumbnailUrl() {
|
|
||||||
return thumbnailUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumbnailUrl(final String thumbnailUrl) {
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTypeLabelBundle() {
|
|
||||||
return typeLabelBundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypeLabelBundle(final String typeLabelBundle) {
|
|
||||||
this.typeLabelBundle = typeLabelBundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTypeLabelKey() {
|
|
||||||
return typeLabelKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypeLabelKey(final String typeLabelKey) {
|
|
||||||
this.typeLabelKey = typeLabelKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getCreated() {
|
|
||||||
if (created == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return new Date(created.getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setCreated(final Date created) {
|
|
||||||
if (created == null) {
|
|
||||||
this.created = null;
|
|
||||||
} else {
|
|
||||||
this.created = new Date(created.getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getLastModified() {
|
|
||||||
if (lastModified == null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return new Date(lastModified.getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setLastModified(final Date lastModified) {
|
|
||||||
if (lastModified == null) {
|
|
||||||
this.lastModified = null;
|
|
||||||
} else {
|
|
||||||
this.lastModified = new Date(lastModified.getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDeletable() {
|
|
||||||
return deletable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeletable(final boolean deletable) {
|
|
||||||
this.deletable = deletable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFolder() {
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFolder(final boolean folder) {
|
|
||||||
this.folder = folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Interface for the CDI backend for the forms to manage assets.To avoid
|
|
||||||
* problems with transactions etc.
|
|
||||||
*
|
|
||||||
* the Bebop based forms should access any other CDI beans beside the
|
|
||||||
* approbriate implementation of this interface. To minimize the efford to
|
|
||||||
* create an implementation the {@link AbstractAssetFormController} class should
|
|
||||||
* be used. This class provides basic implementations for most methods.
|
|
||||||
*
|
|
||||||
* Implementations of the methods defined by this interface should annotated
|
|
||||||
* with {@code @Transactional(Transactional.TxType.REQUIRED)}.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*
|
|
||||||
* @param <T> The type asset managed by this controller.
|
|
||||||
*/
|
|
||||||
public interface AssetFormController<T extends Asset> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the data for the forms from the asset.
|
|
||||||
*
|
|
||||||
* @param assetId The ID of the asset.
|
|
||||||
* @param assetType
|
|
||||||
* @param selectedLocale The selected locale
|
|
||||||
*
|
|
||||||
* @return The values of the properties of the asset for the the selected
|
|
||||||
* locale.
|
|
||||||
*/
|
|
||||||
Map<String, Object> getAssetData(Long assetId,
|
|
||||||
Class<T> assetType,
|
|
||||||
Locale selectedLocale);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the asset with the provided data and saves the changes.
|
|
||||||
*
|
|
||||||
* @param assetId
|
|
||||||
* @param selectedLocale
|
|
||||||
* @param assetType
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
void updateAsset(Long assetId,
|
|
||||||
Locale selectedLocale,
|
|
||||||
Class<T> assetType,
|
|
||||||
Map<String, Object> data);
|
|
||||||
|
|
||||||
long createAsset(Folder inFolder,
|
|
||||||
Locale selectedLocale,
|
|
||||||
Class<T> assetType,
|
|
||||||
Map<String, Object> data);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines in which locales the provided asset is available.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param assetId
|
|
||||||
* @param assetType
|
|
||||||
*
|
|
||||||
* @return A list of the locales for which the asset has data.
|
|
||||||
*/
|
|
||||||
List<Locale> availableLocales(Long assetId, Class<T> assetType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines for which the provided asset has no data.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param assetId
|
|
||||||
* @param assetType
|
|
||||||
*
|
|
||||||
* @return A list of the locales for which the asset has data yet.
|
|
||||||
*/
|
|
||||||
List<Locale> creatableLocales(Long assetId, Class<T> assetType);
|
|
||||||
|
|
||||||
void addLocale(final Long assetId,
|
|
||||||
final Locale locale,
|
|
||||||
final Class<T> assetType);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.enterprise.inject.Any;
|
|
||||||
import javax.enterprise.inject.Instance;
|
|
||||||
import javax.enterprise.util.AnnotationLiteral;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
public class AssetFormControllers {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
@Any
|
|
||||||
private Instance<AssetFormController<?>> controllers;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Asset> AssetFormController<T> findController(
|
|
||||||
final Class<T> assetType) {
|
|
||||||
|
|
||||||
final IsControllerForAssetTypeLiteral literal
|
|
||||||
= new IsControllerForAssetTypeLiteral(
|
|
||||||
assetType);
|
|
||||||
|
|
||||||
final Instance<AssetFormController<?>> instance = controllers
|
|
||||||
.select(literal);
|
|
||||||
|
|
||||||
if (instance.isUnsatisfied()) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"No controller for asset type \"%s\".",
|
|
||||||
assetType.getClass().getName()));
|
|
||||||
} else {
|
|
||||||
return (AssetFormController<T>) instance.iterator().next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class IsControllerForAssetTypeLiteral
|
|
||||||
extends AnnotationLiteral<IsControllerForAssetType>
|
|
||||||
implements IsControllerForAssetType {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private final Class<? extends Asset> assetType;
|
|
||||||
|
|
||||||
public IsControllerForAssetTypeLiteral(
|
|
||||||
final Class<? extends Asset> assetType) {
|
|
||||||
|
|
||||||
this.assetType = assetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Asset> value() {
|
|
||||||
|
|
||||||
return assetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,114 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.form.Widget;
|
|
||||||
import com.arsdigita.bebop.parameters.LongParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.assets.AssetTypeInfo;
|
|
||||||
import org.librecms.assets.AssetTypesManager;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A widget for selecting an asset. The widget does not contain any other
|
|
||||||
* widgets, only the information required to create an HTML/JavaScript dialog
|
|
||||||
* for selecting an asset. To create the dialog the
|
|
||||||
* {@link org.librecms.contentsection.rs.Assets} class can be used which
|
|
||||||
* provides several methods for getting the assets of an content section.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class AssetSearchWidget extends Widget {
|
|
||||||
|
|
||||||
private Class<? extends Asset> type;
|
|
||||||
|
|
||||||
public AssetSearchWidget(final String name) {
|
|
||||||
super(new LongParameter(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssetSearchWidget(final String name,
|
|
||||||
final Class<? extends Asset> type) {
|
|
||||||
this(name);
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCompound() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getType() {
|
|
||||||
return "asset-search-widget";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getElementTag() {
|
|
||||||
return "cms:asset-search-widget";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateWidget(final PageState state,
|
|
||||||
final Element parent) {
|
|
||||||
|
|
||||||
final Element widget = parent.newChildElement(getElementTag(),
|
|
||||||
CMS.CMS_XML_NS);
|
|
||||||
|
|
||||||
widget.addAttribute("name", getName());
|
|
||||||
|
|
||||||
if (type != null) {
|
|
||||||
widget.addAttribute("asset-type", type.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
widget.addAttribute("content-section", section.getLabel());
|
|
||||||
|
|
||||||
final Long value = (Long) getValue(state);
|
|
||||||
if (value != null) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final AssetSearchWidgetController controller = cdiUtil
|
|
||||||
.findBean(AssetSearchWidgetController.class);
|
|
||||||
|
|
||||||
final Map<String, String> data = controller.getData(value);
|
|
||||||
|
|
||||||
final Element selected = widget
|
|
||||||
.newChildElement("cms:selected-asset", CMS.CMS_XML_NS);
|
|
||||||
selected.addAttribute(
|
|
||||||
"assetId", data.get(AssetSearchWidgetController.OBJECT_ID)
|
|
||||||
);
|
|
||||||
selected.addAttribute("title",
|
|
||||||
data.get(AssetSearchWidgetController.TITLE));
|
|
||||||
selected.addAttribute("type",
|
|
||||||
data.get(AssetSearchWidgetController.TYPE));
|
|
||||||
|
|
||||||
exportAttributes(widget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.assets.AssetTypeInfo;
|
|
||||||
import org.librecms.assets.AssetTypesManager;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
public class AssetSearchWidgetController {
|
|
||||||
|
|
||||||
protected static final String OBJECT_ID = "objectId";
|
|
||||||
protected static final String TYPE = "type";
|
|
||||||
protected static final String TITLE = "title";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetTypesManager typesManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private GlobalizationHelper globalizationHelper;
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public Map<String, String> getData(final long assetId) {
|
|
||||||
|
|
||||||
final Asset asset = assetRepository
|
|
||||||
.findById(assetId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No Asset with ID %d in the database.", assetId)));
|
|
||||||
|
|
||||||
final Map<String, String> data = new HashMap<>();
|
|
||||||
|
|
||||||
data.put(OBJECT_ID, Long.toString(asset.getObjectId()));
|
|
||||||
|
|
||||||
data.put(TITLE,
|
|
||||||
globalizationHelper
|
|
||||||
.getValueFromLocalizedString(asset.getTitle()));
|
|
||||||
final AssetTypeInfo typeInfo = typesManager
|
|
||||||
.getAssetTypeInfo(asset.getClass().getName());
|
|
||||||
final ResourceBundle bundle = ResourceBundle
|
|
||||||
.getBundle(typeInfo.getLabelBundle(),
|
|
||||||
globalizationHelper.getNegotiatedLocale());
|
|
||||||
final String typeLabel = bundle.getString(typeInfo.getLabelKey());
|
|
||||||
|
|
||||||
data.put(TYPE, typeLabel);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.inject.Qualifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@Qualifier
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({
|
|
||||||
ElementType.METHOD,
|
|
||||||
ElementType.FIELD,
|
|
||||||
ElementType.PARAMETER,
|
|
||||||
ElementType.TYPE
|
|
||||||
})
|
|
||||||
public @interface IsControllerForAssetType {
|
|
||||||
|
|
||||||
Class<? extends Asset> value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.form.Widget;
|
|
||||||
import com.arsdigita.bebop.parameters.LongParameter;
|
|
||||||
import com.arsdigita.cms.CMS;
|
|
||||||
import com.arsdigita.xml.Element;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.contentsection.ContentItem;
|
|
||||||
import org.librecms.contentsection.ContentItemRepository;
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
|
||||||
import org.librecms.contenttypes.ContentTypeInfo;
|
|
||||||
import org.librecms.contenttypes.ContentTypesManager;
|
|
||||||
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class ItemSearchWidget extends Widget {
|
|
||||||
|
|
||||||
private Class<? extends ContentItem> type;
|
|
||||||
|
|
||||||
public ItemSearchWidget(final String name) {
|
|
||||||
super(new LongParameter(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCompound() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getType() {
|
|
||||||
return "item-search-widget";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getElementTag() {
|
|
||||||
return "cms:item-search-widget";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateWidget(final PageState state,
|
|
||||||
final Element parent) {
|
|
||||||
|
|
||||||
final Element widget = parent.newChildElement(getElementTag(),
|
|
||||||
CMS.CMS_XML_NS);
|
|
||||||
|
|
||||||
widget.addAttribute("name", getName());
|
|
||||||
widget.addAttribute("content-section",
|
|
||||||
CMS.getContext().getContentSection().getLabel());
|
|
||||||
|
|
||||||
if (type != null) {
|
|
||||||
widget.addAttribute("asset-type", type.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// final ContentSection section = CMS.getContext().getContentSection();
|
|
||||||
// widget.addAttribute("content-section", section.getLabel());
|
|
||||||
|
|
||||||
final Long value = (Long) getValue(state);
|
|
||||||
if (value != null) {
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
final ContentItemRepository itemRepo = cdiUtil
|
|
||||||
.findBean(ContentItemRepository.class);
|
|
||||||
final ContentTypesManager typesManager = cdiUtil
|
|
||||||
.findBean(ContentTypesManager.class);
|
|
||||||
final GlobalizationHelper globalizationHelper = cdiUtil
|
|
||||||
.findBean(GlobalizationHelper.class);
|
|
||||||
|
|
||||||
final ContentItem item = itemRepo
|
|
||||||
.findById(value)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String
|
|
||||||
.format("No ContentItem with ID %d in the database.", value)));
|
|
||||||
|
|
||||||
final Element selected = widget
|
|
||||||
.newChildElement("cms:selected-content-item", CMS.CMS_XML_NS);
|
|
||||||
selected.addAttribute("contentItemId",
|
|
||||||
Long.toString(item.getObjectId()));
|
|
||||||
selected.addAttribute("name", item.getDisplayName());
|
|
||||||
selected.addAttribute(
|
|
||||||
"title",
|
|
||||||
globalizationHelper.getValueFromLocalizedString(item.getTitle()));
|
|
||||||
final ContentTypeInfo typeInfo = typesManager
|
|
||||||
.getContentTypeInfo(item.getClass());
|
|
||||||
final ResourceBundle bundle = ResourceBundle
|
|
||||||
.getBundle(typeInfo.getLabelBundle(),
|
|
||||||
globalizationHelper.getNegotiatedLocale());
|
|
||||||
final String typeLabel = bundle.getString(typeInfo.getLabelKey());
|
|
||||||
selected.addAttribute("type", typeLabel);
|
|
||||||
|
|
||||||
exportAttributes(widget);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.Text;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.cms.ui.FileUploadSection;
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetForm;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.BinaryAsset;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base form for assets which extend {@link BinaryAsset}.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T> Type of binary asset
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBinaryAssetForm<T extends BinaryAsset>
|
|
||||||
extends AbstractAssetForm<T> {
|
|
||||||
|
|
||||||
private TextArea description;
|
|
||||||
|
|
||||||
private Text fileName;
|
|
||||||
|
|
||||||
private Text mimeType;
|
|
||||||
|
|
||||||
private Text size;
|
|
||||||
|
|
||||||
private FileUploadSection fileUpload;
|
|
||||||
|
|
||||||
public AbstractBinaryAssetForm(final AssetPane assetPane) {
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addWidgets() {
|
|
||||||
|
|
||||||
final BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL);
|
|
||||||
|
|
||||||
panel.add(new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.assets.binaryasset.description",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
description = new TextArea("binaryasset-description");
|
|
||||||
panel.add(description);
|
|
||||||
|
|
||||||
panel.add(new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.assets.binaryasset.filename",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
fileName = new Text();
|
|
||||||
panel.add(fileName);
|
|
||||||
|
|
||||||
panel.add(new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.assets.binaryasset.mimetype",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
mimeType = new Text();
|
|
||||||
panel.add(mimeType);
|
|
||||||
|
|
||||||
panel.add(new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.assets.binaryasset.size",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
size = new Text();
|
|
||||||
panel.add(size);
|
|
||||||
|
|
||||||
fileUpload = new FileUploadSection(
|
|
||||||
new GlobalizedMessage("cms.ui.assets.binaryasset.mimetype",
|
|
||||||
CmsConstants.CMS_BUNDLE),
|
|
||||||
"",
|
|
||||||
"");
|
|
||||||
panel.add(fileUpload);
|
|
||||||
|
|
||||||
add(panel);
|
|
||||||
|
|
||||||
setEncType(CmsConstants.FORM_ENCTYPE_MULTIPART);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.initForm(state, data);
|
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
|
|
||||||
description.setValue(state,
|
|
||||||
data.get("description"));
|
|
||||||
|
|
||||||
if (data.containsKey("data")) {
|
|
||||||
|
|
||||||
final byte[] binaryData = (byte[]) data.get("data");
|
|
||||||
if (binaryData.length == 0) {
|
|
||||||
fileName.setText("-");
|
|
||||||
mimeType.setText("-");
|
|
||||||
size.setText("-");
|
|
||||||
} else {
|
|
||||||
fileName.setText((String) data.get("fileName"));
|
|
||||||
mimeType.setText((String) data.get("mimeType"));
|
|
||||||
size.setText(Long.toString((long) data.get("size")));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
fileName.setText("-");
|
|
||||||
mimeType.setText("-");
|
|
||||||
size.setText("-");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void showLocale(final PageState state) {
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
if (selectedAssetId != null) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = getController()
|
|
||||||
.getAssetData(selectedAssetId,
|
|
||||||
getAssetClass(),
|
|
||||||
getSelectedLocale(state));
|
|
||||||
|
|
||||||
description
|
|
||||||
.setValue(
|
|
||||||
state,
|
|
||||||
data
|
|
||||||
.get(AbstractBinaryAssetFormController.DESCRIPTION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> collectData(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
return getFileData(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Object> getFileData(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final File file = fileUpload.getFile(event);
|
|
||||||
if (file == null) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
} else {
|
|
||||||
final Path path = file.toPath();
|
|
||||||
final byte[] data;
|
|
||||||
try {
|
|
||||||
data = Files.readAllBytes(path);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new FormProcessException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Map<String, Object> assetData = new HashMap<>();
|
|
||||||
|
|
||||||
assetData.put(AbstractBinaryAssetFormController.DATA,
|
|
||||||
data);
|
|
||||||
assetData.put(AbstractBinaryAssetFormController.FILE_NAME,
|
|
||||||
fileUpload.getFileName(event));
|
|
||||||
assetData.put(AbstractBinaryAssetFormController.SIZE,
|
|
||||||
data.length);
|
|
||||||
assetData.put(AbstractBinaryAssetFormController.MIME_TYPE,
|
|
||||||
fileUpload.getMimeType(event));
|
|
||||||
|
|
||||||
return assetData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetFormController;
|
|
||||||
|
|
||||||
import org.librecms.assets.BinaryAsset;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.activation.MimeType;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBinaryAssetFormController<T extends BinaryAsset>
|
|
||||||
extends AbstractAssetFormController<T> {
|
|
||||||
|
|
||||||
protected static final String DESCRIPTION = "description";
|
|
||||||
|
|
||||||
protected static final String FILE_NAME = "fileName";
|
|
||||||
|
|
||||||
protected static final String MIME_TYPE = "mimeType";
|
|
||||||
|
|
||||||
protected static final String DATA = "data";
|
|
||||||
|
|
||||||
protected static final String SIZE = "size";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
protected Map<String, Object> getAssetData(final T asset,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
|
|
||||||
final String description = asset
|
|
||||||
.getDescription()
|
|
||||||
.getValue(selectedLocale);
|
|
||||||
|
|
||||||
data.put(DESCRIPTION, description);
|
|
||||||
data.put(FILE_NAME, asset.getFileName());
|
|
||||||
data.put(MIME_TYPE, asset.getMimeType());
|
|
||||||
data.put(DATA, asset.getData());
|
|
||||||
data.put(SIZE, asset.getSize());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public void updateAssetProperties(final T asset,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
if (data.containsKey(DESCRIPTION)) {
|
|
||||||
asset.getDescription().putValue(selectedLocale,
|
|
||||||
(String) data.get(DESCRIPTION));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(FILE_NAME)) {
|
|
||||||
asset.setFileName((String) data.get(FILE_NAME));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(MIME_TYPE)) {
|
|
||||||
asset.setMimeType((MimeType) data.get(MIME_TYPE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(DATA)) {
|
|
||||||
//asset.setData((byte[]) data.get(DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(SIZE)) {
|
|
||||||
asset.setSize((long) data.get(SIZE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormData;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.FormValidationListener;
|
|
||||||
import com.arsdigita.bebop.form.TextArea;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetForm;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.Bookmark;
|
|
||||||
import org.librecms.contentsection.Asset;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract base form for all forms for {@link BookmarkAsset}s.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T> Type of the Bookmark Asset.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBookmarkForm<T extends Bookmark>
|
|
||||||
extends AbstractAssetForm<T> {
|
|
||||||
|
|
||||||
private TextArea description;
|
|
||||||
|
|
||||||
private TextField url;
|
|
||||||
|
|
||||||
public AbstractBookmarkForm(final AssetPane assetPane) {
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addWidgets() {
|
|
||||||
|
|
||||||
add(new Label(
|
|
||||||
new GlobalizedMessage("cms.ui.assets.bookmark.description",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
description = new TextArea("bookmark-description");
|
|
||||||
add(description);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage("cms.ui.assets.bookmark.url",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
url = new TextField("bookmark-url");
|
|
||||||
add(url);
|
|
||||||
|
|
||||||
addValidationListener(new FormValidationListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final FormData data = event.getFormData();
|
|
||||||
|
|
||||||
try {
|
|
||||||
new URL((String) url.getValue(state));
|
|
||||||
} catch (MalformedURLException ex) {
|
|
||||||
data.addError(new GlobalizedMessage(
|
|
||||||
"cms.ui.assets.bookmark.url.malformed",
|
|
||||||
CmsConstants.CMS_BUNDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.initForm(state, data);
|
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
|
|
||||||
description
|
|
||||||
.setValue(
|
|
||||||
state,
|
|
||||||
data.get(AbstractBookmarkFormController.DESCRIPTION));
|
|
||||||
url.setValue(state, data.get(AbstractBookmarkFormController.URL));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void showLocale(final PageState state) {
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
if (selectedAssetId != null) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = getController()
|
|
||||||
.getAssetData(selectedAssetId,
|
|
||||||
getAssetClass(),
|
|
||||||
getSelectedLocale(state));
|
|
||||||
|
|
||||||
description.setValue(
|
|
||||||
state,
|
|
||||||
data.get(AbstractBinaryAssetFormController.DESCRIPTION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateData(final Bookmark bookmark,
|
|
||||||
final PageState state) {
|
|
||||||
bookmark
|
|
||||||
.getDescription()
|
|
||||||
.putValue(getSelectedLocale(state),
|
|
||||||
(String) description.getValue(state));
|
|
||||||
|
|
||||||
bookmark.setUrl((String) url.getValue(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetFormController;
|
|
||||||
|
|
||||||
import org.librecms.assets.Bookmark;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBookmarkFormController<T extends Bookmark>
|
|
||||||
extends AbstractAssetFormController<T> {
|
|
||||||
|
|
||||||
protected static final String DESCRIPTION = "description";
|
|
||||||
|
|
||||||
protected static final String URL = "url";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> getAssetData(final T asset,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final String description = asset
|
|
||||||
.getDescription()
|
|
||||||
.getValue(selectedLocale);
|
|
||||||
|
|
||||||
final String url = asset.getUrl();
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
|
|
||||||
data.put("description", description);
|
|
||||||
data.put("url", url);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateAssetProperties(final T asset,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
if (data.containsKey(DESCRIPTION)) {
|
|
||||||
|
|
||||||
asset.getDescription().putValue(selectedLocale,
|
|
||||||
(String) data.get(DESCRIPTION));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.containsKey(URL)) {
|
|
||||||
|
|
||||||
asset.setUrl((String) data.get(URL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,434 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
|
||||||
import com.arsdigita.bebop.Component;
|
|
||||||
import com.arsdigita.bebop.ControlLink;
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.Table;
|
|
||||||
import com.arsdigita.bebop.Text;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintEvent;
|
|
||||||
import com.arsdigita.bebop.event.PrintListener;
|
|
||||||
import com.arsdigita.bebop.event.TableActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.TableActionListener;
|
|
||||||
import com.arsdigita.bebop.form.Option;
|
|
||||||
import com.arsdigita.bebop.form.SingleSelect;
|
|
||||||
import com.arsdigita.bebop.form.Submit;
|
|
||||||
import com.arsdigita.bebop.form.TextField;
|
|
||||||
import com.arsdigita.bebop.parameters.StringParameter;
|
|
||||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
|
||||||
import com.arsdigita.bebop.table.TableColumn;
|
|
||||||
import com.arsdigita.bebop.table.TableColumnModel;
|
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
|
||||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetForm;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetSearchWidget;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
import com.arsdigita.util.LockableImpl;
|
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.ContactEntryKey;
|
|
||||||
import org.librecms.assets.ContactableEntity;
|
|
||||||
import org.librecms.assets.PostalAddress;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TooManyListenersException;
|
|
||||||
|
|
||||||
import static org.librecms.CmsConstants.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractContactableEntityForm<T extends ContactableEntity>
|
|
||||||
extends AbstractAssetForm<T> {
|
|
||||||
|
|
||||||
private static final int COL_CONTACT_ENTRIES_KEY = 0;
|
|
||||||
|
|
||||||
private static final int COL_CONTACT_ENTRIES_VALUE = 1;
|
|
||||||
|
|
||||||
private static final int COL_CONTACT_ENTRIES_REMOVE = 2;
|
|
||||||
|
|
||||||
private SimpleContainer contactEntriesContainer;
|
|
||||||
|
|
||||||
private Table contactEntriesTable;
|
|
||||||
|
|
||||||
private SingleSelect contactEntryKeySelect;
|
|
||||||
|
|
||||||
private TextField contactEntryValueField;
|
|
||||||
|
|
||||||
private Submit addContactEntryLink;
|
|
||||||
|
|
||||||
private AssetSearchWidget postalAddressSearchWidget;
|
|
||||||
|
|
||||||
public AbstractContactableEntityForm(final AssetPane assetPane) {
|
|
||||||
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addWidgets() {
|
|
||||||
|
|
||||||
addPropertyWidgets();
|
|
||||||
|
|
||||||
contactEntriesContainer = new BoxPanel(BoxPanel.VERTICAL) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible(final PageState state) {
|
|
||||||
return getSelectedAssetId(state) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
add(contactEntriesContainer);
|
|
||||||
|
|
||||||
contactEntriesTable = buildContactEntriesTable();
|
|
||||||
contactEntriesContainer.add(contactEntriesTable);
|
|
||||||
|
|
||||||
contactEntryKeySelect = new SingleSelect(new StringParameter(
|
|
||||||
"contactentry-key"));
|
|
||||||
try {
|
|
||||||
contactEntryKeySelect
|
|
||||||
.addPrintListener(new ContactEntryKeySelectPrintListener());
|
|
||||||
} catch (TooManyListenersException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
contactEntriesContainer.add(new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.key",
|
|
||||||
CMS_BUNDLE))
|
|
||||||
);
|
|
||||||
contactEntriesContainer.add(contactEntryKeySelect);
|
|
||||||
|
|
||||||
contactEntryValueField = new TextField("contact-entry-value");
|
|
||||||
contactEntriesContainer.add(new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.value",
|
|
||||||
CMS_BUNDLE))
|
|
||||||
);
|
|
||||||
contactEntriesContainer.add(contactEntryValueField);
|
|
||||||
|
|
||||||
addContactEntryLink = new Submit(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.add",
|
|
||||||
CMS_BUNDLE)
|
|
||||||
);
|
|
||||||
contactEntriesContainer.add(addContactEntryLink);
|
|
||||||
|
|
||||||
contactEntriesContainer.add(new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.postaladdress",
|
|
||||||
CMS_BUNDLE))
|
|
||||||
);
|
|
||||||
postalAddressSearchWidget = new AssetSearchWidget(
|
|
||||||
"contactable-postaladdress", PostalAddress.class
|
|
||||||
);
|
|
||||||
contactEntriesContainer.add(postalAddressSearchWidget);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.initForm(state, data);
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
if (selectedAssetId != null) {
|
|
||||||
|
|
||||||
postalAddressSearchWidget.setValue(
|
|
||||||
state,
|
|
||||||
data.get(AbstractContactableEntityFormController.POSTAL_ADDRESS)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> collectData(
|
|
||||||
final FormSectionEvent event) {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
|
|
||||||
if (postalAddressSearchWidget.getValue(state) != null) {
|
|
||||||
|
|
||||||
data.put(AbstractContactableEntityFormController.POSTAL_ADDRESS,
|
|
||||||
postalAddressSearchWidget.getValue(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
if (addContactEntryLink.isSelected(state)) {
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
if (selectedAssetId == null) {
|
|
||||||
throw new FormProcessException(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.assets.none_selected", CMS_BUNDLE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final AbstractContactableEntityFormController<ContactableEntity> controller
|
|
||||||
= (AbstractContactableEntityFormController<ContactableEntity>) getController();
|
|
||||||
|
|
||||||
final String key = (String) contactEntryKeySelect
|
|
||||||
.getValue(state);
|
|
||||||
final String value = (String) contactEntryValueField.getValue(state);
|
|
||||||
|
|
||||||
controller.addContactEntry(key, value, selectedAssetId);
|
|
||||||
|
|
||||||
contactEntryKeySelect.setValue(state, null);
|
|
||||||
contactEntryValueField.setValue(state, null);
|
|
||||||
} else {
|
|
||||||
super.process(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void addPropertyWidgets();
|
|
||||||
|
|
||||||
private Table buildContactEntriesTable() {
|
|
||||||
|
|
||||||
final Table table = new Table();
|
|
||||||
// {
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public boolean isVisible(final PageState state) {
|
|
||||||
// return getSelectedAsset(state).isPresent();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
final TableColumnModel columnModel = table.getColumnModel();
|
|
||||||
columnModel.add(new TableColumn(
|
|
||||||
COL_CONTACT_ENTRIES_KEY,
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.key",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
columnModel.add(new TableColumn(
|
|
||||||
COL_CONTACT_ENTRIES_VALUE,
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.value",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
columnModel.add(new TableColumn(
|
|
||||||
COL_CONTACT_ENTRIES_REMOVE,
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.remove",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
table.setModelBuilder(new ContactEntriesTableModelBuilder());
|
|
||||||
|
|
||||||
table
|
|
||||||
.getColumn(COL_CONTACT_ENTRIES_REMOVE)
|
|
||||||
.setCellRenderer(new ContactEntryRemoveCellRenderer());
|
|
||||||
|
|
||||||
table.setEmptyView(
|
|
||||||
new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable.contactentries.none",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
table.addTableActionListener(new TableActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cellSelected(final TableActionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final Integer rowKey = (Integer) event.getRowKey();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final AbstractContactableEntityFormController<ContactableEntity> controller
|
|
||||||
= (AbstractContactableEntityFormController<ContactableEntity>) getController();
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
final Long selectedId = getSelectedAssetId(state);
|
|
||||||
if (selectedId != null) {
|
|
||||||
controller.removeContactEntry(rowKey, selectedId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void headSelected(final TableActionEvent event) {
|
|
||||||
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContactEntriesTableModelBuilder
|
|
||||||
extends LockableImpl implements TableModelBuilder {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TableModel makeModel(final Table table,
|
|
||||||
final PageState state) {
|
|
||||||
|
|
||||||
final Long selectedId = getSelectedAssetId(state);
|
|
||||||
if (selectedId == null) {
|
|
||||||
throw new RuntimeException("No asset selected.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final AbstractContactableEntityFormController<ContactableEntity> controller
|
|
||||||
= (AbstractContactableEntityFormController<ContactableEntity>) getController();
|
|
||||||
final List<String[]> contactEntries = controller
|
|
||||||
.getContactEntries(selectedId, getSelectedLocale(state));
|
|
||||||
|
|
||||||
return new ContactEntriesTableModel(contactEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContactEntriesTableModel implements TableModel {
|
|
||||||
|
|
||||||
private final Iterator<String[]> contactEntries;
|
|
||||||
|
|
||||||
private String[] currentContactEntry;
|
|
||||||
|
|
||||||
public ContactEntriesTableModel(
|
|
||||||
final List<String[]> contactEntries) {
|
|
||||||
|
|
||||||
this.contactEntries = contactEntries.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColumnCount() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean nextRow() {
|
|
||||||
|
|
||||||
if (contactEntries.hasNext()) {
|
|
||||||
currentContactEntry = contactEntries.next();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getElementAt(final int columnIndex) {
|
|
||||||
|
|
||||||
switch (columnIndex) {
|
|
||||||
case COL_CONTACT_ENTRIES_KEY:
|
|
||||||
return currentContactEntry[1];
|
|
||||||
case COL_CONTACT_ENTRIES_VALUE:
|
|
||||||
return currentContactEntry[2];
|
|
||||||
case COL_CONTACT_ENTRIES_REMOVE:
|
|
||||||
return new Label(
|
|
||||||
new GlobalizedMessage(
|
|
||||||
"cms.ui.authoring.assets.contactable"
|
|
||||||
+ ".contactentries.remove",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"Illegal column index %d.", columnIndex));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getKeyAt(int columnIndex) {
|
|
||||||
return currentContactEntry[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContactEntryRemoveCellRenderer implements TableCellRenderer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getComponent(final Table table,
|
|
||||||
final PageState state,
|
|
||||||
final Object value,
|
|
||||||
final boolean isSelected,
|
|
||||||
final Object key,
|
|
||||||
final int row,
|
|
||||||
final int column) {
|
|
||||||
|
|
||||||
return new ControlLink((Component) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContactEntryKeySelectPrintListener implements PrintListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare(final PrintEvent event) {
|
|
||||||
|
|
||||||
final SingleSelect target = (SingleSelect) event.getTarget();
|
|
||||||
target.clearOptions();
|
|
||||||
|
|
||||||
target.addOption(
|
|
||||||
new Option("",
|
|
||||||
new Label(new GlobalizedMessage("cms.ui.select_one",
|
|
||||||
CMS_BUNDLE)))
|
|
||||||
);
|
|
||||||
|
|
||||||
final AbstractContactableEntityFormController<?> controller = (AbstractContactableEntityFormController<?>) getController();
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final List<String[]> keys = controller
|
|
||||||
.findAvailableContactEntryKeys(getSelectedLocale(state));
|
|
||||||
|
|
||||||
for (final String[] key : keys) {
|
|
||||||
target.addOption(new Option(key[0], new Text(key[1])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.assets.AbstractAssetFormController;
|
|
||||||
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
|
||||||
import org.librecms.assets.ContactEntry;
|
|
||||||
import org.librecms.assets.ContactEntryKey;
|
|
||||||
import org.librecms.assets.ContactEntryKeyByLabelComparator;
|
|
||||||
import org.librecms.assets.ContactEntryKeyRepository;
|
|
||||||
import org.librecms.assets.ContactableEntity;
|
|
||||||
import org.librecms.assets.ContactableEntityManager;
|
|
||||||
import org.librecms.assets.ContactableEntityRepository;
|
|
||||||
import org.librecms.assets.PostalAddress;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractContactableEntityFormController<T extends ContactableEntity>
|
|
||||||
extends AbstractAssetFormController<T> {
|
|
||||||
|
|
||||||
protected static final String POSTAL_ADDRESS = "postalAddress";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContactableEntityRepository contactableEntityRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContactableEntityManager contactableEntityManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ContactEntryKeyRepository keyRepository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private GlobalizationHelper globalizationHelper;
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> getAssetData(final T asset,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
|
|
||||||
final PostalAddress postalAddress = asset.getPostalAddress();
|
|
||||||
if (postalAddress != null) {
|
|
||||||
data.put(POSTAL_ADDRESS, postalAddress.getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateAssetProperties(final T asset,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
if (data.containsKey(POSTAL_ADDRESS)) {
|
|
||||||
|
|
||||||
final long addressId = (long) data.get(POSTAL_ADDRESS);
|
|
||||||
final PostalAddress postalAddress = assetRepository
|
|
||||||
.findById(addressId, PostalAddress.class)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No PostalAddress with ID %d found.", addressId)));
|
|
||||||
|
|
||||||
contactableEntityManager
|
|
||||||
.addPostalAddressToContactableEntity(postalAddress, asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the contact entries of the provided contentable entity for the
|
|
||||||
* provided language.
|
|
||||||
*
|
|
||||||
* @param contactableId The ID of the contactable entity.
|
|
||||||
* @param selectedLocale The selected locale.
|
|
||||||
*
|
|
||||||
* @return An list of the contact entires
|
|
||||||
*/
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public List<String[]> getContactEntries(
|
|
||||||
final Long contactableId, final Locale selectedLocale) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(contactableId,
|
|
||||||
"Can't get contact entries from null.");
|
|
||||||
|
|
||||||
final ContactableEntity entity = contactableEntityRepository
|
|
||||||
.findById(contactableId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No ContactEntity with ID %d found.", contactableId)));
|
|
||||||
|
|
||||||
return entity
|
|
||||||
.getContactEntries()
|
|
||||||
.stream()
|
|
||||||
.map(contactEntry -> toContactEntryArray(contactEntry,
|
|
||||||
selectedLocale))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] toContactEntryArray(final ContactEntry entry,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final String key = entry.getKey().getEntryKey();
|
|
||||||
final String label = entry.getKey().getLabel().getValue(selectedLocale);
|
|
||||||
final String value = entry.getValue();
|
|
||||||
|
|
||||||
return new String[]{key, label, value};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public void addContactEntry(final String contactEntryKey,
|
|
||||||
final String contactEntryValue,
|
|
||||||
final Long toContactableEntityWithId) {
|
|
||||||
|
|
||||||
final ContactableEntity contactable = contactableEntityRepository
|
|
||||||
.findById(toContactableEntityWithId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No ContactableEntity with ID %d found",
|
|
||||||
toContactableEntityWithId)));
|
|
||||||
|
|
||||||
final ContactEntryKey key = keyRepository
|
|
||||||
.findByEntryKey(contactEntryKey)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No ContactEntryKey with key \"%s\" found.", contactEntryKey)));
|
|
||||||
final ContactEntry entry = new ContactEntry();
|
|
||||||
entry.setKey(key);
|
|
||||||
entry.setValue(contactEntryValue);
|
|
||||||
entry.setOrder(contactable.getContactEntries().size());
|
|
||||||
|
|
||||||
contactableEntityManager
|
|
||||||
.addContactEntryToContactableEntity(entry, contactable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public void removeContactEntry(final int withIndex,
|
|
||||||
final Long fromContactableEntityWithId) {
|
|
||||||
|
|
||||||
final ContactableEntity contactable = contactableEntityRepository
|
|
||||||
.findById(fromContactableEntityWithId)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No ContactableEntity with ID %d found",
|
|
||||||
fromContactableEntityWithId)));
|
|
||||||
|
|
||||||
if (contactable.getContactEntries().size() > withIndex) {
|
|
||||||
|
|
||||||
final ContactEntry contactEntry = contactable
|
|
||||||
.getContactEntries()
|
|
||||||
.get(withIndex);
|
|
||||||
contactableEntityManager.removeContactEntryFromContactableEntity(
|
|
||||||
contactEntry, contactable
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
|
||||||
public List<String[]> findAvailableContactEntryKeys(
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
return keyRepository
|
|
||||||
.findAll()
|
|
||||||
.stream()
|
|
||||||
.sorted(new ContactEntryKeyByLabelComparator(selectedLocale))
|
|
||||||
.map(key -> buildContactEntryKeyArray(key,
|
|
||||||
selectedLocale))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] buildContactEntryKeyArray(
|
|
||||||
final ContactEntryKey contactEntryKey, final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final String key = contactEntryKey.getEntryKey();
|
|
||||||
final String label = contactEntryKey.getLabel().getValue(selectedLocale);
|
|
||||||
|
|
||||||
return new String[]{key, label};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetSearchWidget;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.AudioAsset;
|
|
||||||
import org.librecms.assets.LegalMetadata;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class AudioForm extends AbstractBinaryAssetForm<AudioAsset> {
|
|
||||||
|
|
||||||
private AssetSearchWidget assetSearchWidget;
|
|
||||||
|
|
||||||
public AudioForm(final AssetPane assetPane) {
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addWidgets() {
|
|
||||||
|
|
||||||
assetSearchWidget = new AssetSearchWidget("legal-metadata",
|
|
||||||
LegalMetadata.class);
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.assets.audio.legal_metadata.label",
|
|
||||||
CmsConstants.CMS_BUNDLE
|
|
||||||
)));
|
|
||||||
add(assetSearchWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.initForm(state, data);
|
|
||||||
|
|
||||||
if (data.containsKey(AudioFormController.LEGAL_METADATA_ID)) {
|
|
||||||
|
|
||||||
final Long legalMetadataId = (Long) data
|
|
||||||
.get(AudioFormController.LEGAL_METADATA_ID);
|
|
||||||
if (legalMetadataId != null) {
|
|
||||||
assetSearchWidget.setValue(state, legalMetadataId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<AudioAsset> getAssetClass() {
|
|
||||||
return AudioAsset.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected Asset createAsset(final FormSectionEvent event)
|
|
||||||
// throws FormProcessException {
|
|
||||||
//
|
|
||||||
// final AudioAsset audioAsset = (AudioAsset) super.createAsset(event);
|
|
||||||
//
|
|
||||||
// final PageState state = event.getPageState();
|
|
||||||
//
|
|
||||||
// updateData(audioAsset, state);
|
|
||||||
//
|
|
||||||
// return audioAsset;
|
|
||||||
// }
|
|
||||||
// @Override
|
|
||||||
// protected void updateAsset(final Asset asset,
|
|
||||||
// final FormSectionEvent event)
|
|
||||||
// throws FormProcessException {
|
|
||||||
//
|
|
||||||
// super.updateAsset(asset, event);
|
|
||||||
//
|
|
||||||
// final PageState state = event.getPageState();
|
|
||||||
//
|
|
||||||
// final AudioAsset audioAsset = (AudioAsset) asset;
|
|
||||||
//
|
|
||||||
// updateData(audioAsset, state);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected void updateData(final AudioAsset audioAsset,
|
|
||||||
// final PageState state) {
|
|
||||||
//
|
|
||||||
// final Long legalMetadataId = (Long) assetSearchWidget.getValue(state);
|
|
||||||
// if (legalMetadataId != null) {
|
|
||||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
|
||||||
// final AssetRepository assetRepo = cdiUtil.findBean(
|
|
||||||
// AssetRepository.class);
|
|
||||||
// final LegalMetadata legalMetadata = (LegalMetadata) assetRepo
|
|
||||||
// .findById(legalMetadataId)
|
|
||||||
// .orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
// "No LegalMetadata asset with ID %d in the database.",
|
|
||||||
// legalMetadataId)));
|
|
||||||
//
|
|
||||||
// audioAsset.setLegalMetadata(legalMetadata);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected BinaryAsset createBinaryAsset(final PageState state) {
|
|
||||||
// return new AudioAsset();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.assets.IsControllerForAssetType;
|
|
||||||
|
|
||||||
import org.librecms.assets.AudioAsset;
|
|
||||||
import org.librecms.assets.LegalMetadata;
|
|
||||||
import org.librecms.contentsection.AssetRepository;
|
|
||||||
import org.librecms.contentsection.Folder;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
@IsControllerForAssetType(AudioAsset.class)
|
|
||||||
public class AudioFormController extends AbstractBinaryAssetFormController<AudioAsset> {
|
|
||||||
|
|
||||||
protected static final String LEGAL_METADATA_ID = "legalMetadataId";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AssetRepository assetRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> getAssetData(final AudioAsset asset,
|
|
||||||
final Locale selectedLocale) {
|
|
||||||
|
|
||||||
final Map<String, Object> data = super.getAssetData(asset,
|
|
||||||
selectedLocale);
|
|
||||||
|
|
||||||
final LegalMetadata legalMetadata = asset.getLegalMetadata();
|
|
||||||
if (legalMetadata != null) {
|
|
||||||
data.put(LEGAL_METADATA_ID, legalMetadata.getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateAssetProperties(final AudioAsset asset,
|
|
||||||
final Locale selectedLocale,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.updateAssetProperties(asset, selectedLocale, data);
|
|
||||||
|
|
||||||
if (data.containsKey(LEGAL_METADATA_ID)) {
|
|
||||||
|
|
||||||
final long legalMetadataId = (long) data.get(LEGAL_METADATA_ID);
|
|
||||||
|
|
||||||
final LegalMetadata legalMetadata = assetRepository
|
|
||||||
.findById(legalMetadataId, LegalMetadata.class)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
|
||||||
"No LegalMetadata with ID %d found.", legalMetadataId)));
|
|
||||||
|
|
||||||
asset.setLegalMetadata(legalMetadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
|
|
||||||
import org.librecms.assets.Bookmark;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class BookmarkForm extends AbstractBookmarkForm<Bookmark> {
|
|
||||||
|
|
||||||
// private TextArea description;
|
|
||||||
// private TextField url;
|
|
||||||
public BookmarkForm(final AssetPane assetPane) {
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected void addWidgets() {
|
|
||||||
//
|
|
||||||
// add(new Label(
|
|
||||||
// new GlobalizedMessage("cms.ui.assets.bookmark.description",
|
|
||||||
// CmsConstants.CMS_BUNDLE)));
|
|
||||||
// description = new TextArea("bookmark-description");
|
|
||||||
// add(description);
|
|
||||||
//
|
|
||||||
// add(new Label(new GlobalizedMessage("cms.ui.assets.bookmark.url",
|
|
||||||
// CmsConstants.CMS_BUNDLE)));
|
|
||||||
// url = new TextField("bookmark-url");
|
|
||||||
// add(url);
|
|
||||||
//
|
|
||||||
// addValidationListener(new FormValidationListener() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void validate(final FormSectionEvent event)
|
|
||||||
// throws FormProcessException {
|
|
||||||
//
|
|
||||||
// final PageState state = event.getPageState();
|
|
||||||
// final FormData data = event.getFormData();
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// new URL((String) url.getValue(state));
|
|
||||||
// } catch (MalformedURLException ex) {
|
|
||||||
// data.addError(new GlobalizedMessage(
|
|
||||||
// "cms.ui.assets.bookmark.url.malformed",
|
|
||||||
// CmsConstants.CMS_BUNDLE));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected void initForm(final PageState state,
|
|
||||||
// final Optional<Bookmark> selectedAsset) {
|
|
||||||
//
|
|
||||||
// if (selectedAsset.isPresent()) {
|
|
||||||
//
|
|
||||||
// if (!(selectedAsset.get() instanceof Bookmark)) {
|
|
||||||
// throw new IllegalArgumentException(String.format(
|
|
||||||
// "The provided asset must be an instanceof of class '%s' or "
|
|
||||||
// + "an subclass but is an instanceof of class '%s'.",
|
|
||||||
// Bookmark.class.getName(),
|
|
||||||
// selectedAsset.get().getClass().getName()));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final Bookmark bookmark = selectedAsset.get();
|
|
||||||
//
|
|
||||||
// description.setValue(state,
|
|
||||||
// bookmark
|
|
||||||
// .getDescription()
|
|
||||||
// .getValue(getSelectedLocale(state)));
|
|
||||||
// url.setValue(state, bookmark.getUrl());
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected void showLocale(final PageState state) {
|
|
||||||
// final Optional<Bookmark> selectedAsset = getSelectedAsset(state);
|
|
||||||
//
|
|
||||||
// if (selectedAsset.isPresent()) {
|
|
||||||
// if (!(getSelectedAsset(state).get() instanceof Bookmark)) {
|
|
||||||
// throw new IllegalArgumentException(
|
|
||||||
// "Selected asset is not a bookmark");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final Bookmark bookmark = selectedAsset.get();
|
|
||||||
//
|
|
||||||
// description.setValue(state,
|
|
||||||
// bookmark
|
|
||||||
// .getDescription()
|
|
||||||
// .getValue(getSelectedLocale(state)));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Class<Bookmark> getAssetClass() {
|
|
||||||
return Bookmark.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected Asset createAsset(final FormSectionEvent event)
|
|
||||||
// throws FormProcessException {
|
|
||||||
//
|
|
||||||
// Objects.requireNonNull(event);
|
|
||||||
//
|
|
||||||
// final PageState state = event.getPageState();
|
|
||||||
//
|
|
||||||
// final Bookmark bookmark = new Bookmark();
|
|
||||||
//
|
|
||||||
// updateData(bookmark, state);
|
|
||||||
//
|
|
||||||
// return bookmark;
|
|
||||||
// }
|
|
||||||
// protected void updateData(final Bookmark bookmark,
|
|
||||||
// final PageState state) {
|
|
||||||
// bookmark
|
|
||||||
// .getDescription()
|
|
||||||
// .addValue(getSelectedLocale(state),
|
|
||||||
// (String) description.getValue(state));
|
|
||||||
//
|
|
||||||
// bookmark.setUrl((String) url.getValue(state));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected void updateAsset(final Asset asset,
|
|
||||||
// final FormSectionEvent event)
|
|
||||||
// throws FormProcessException {
|
|
||||||
//
|
|
||||||
// Objects.requireNonNull(asset);
|
|
||||||
// Objects.requireNonNull(event);
|
|
||||||
//
|
|
||||||
// final PageState state = event.getPageState();
|
|
||||||
//
|
|
||||||
// if (!(asset instanceof Bookmark)) {
|
|
||||||
// throw new IllegalArgumentException(String.format(
|
|
||||||
// "Provided asset is not an instance of class (or sub class of) "
|
|
||||||
// + "'%s' but is an instance of class '%s'",
|
|
||||||
// Bookmark.class.getName(),
|
|
||||||
// asset.getClass().getName()));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final Bookmark bookmark = (Bookmark) asset;
|
|
||||||
//
|
|
||||||
// updateData(bookmark, state);
|
|
||||||
// }
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> collectData(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.cms.ui.assets.IsControllerForAssetType;
|
|
||||||
|
|
||||||
import org.librecms.assets.Bookmark;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@RequestScoped
|
|
||||||
@IsControllerForAssetType(Bookmark.class)
|
|
||||||
public class BookmarkFormController
|
|
||||||
extends AbstractBookmarkFormController<Bookmark> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2017 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package com.arsdigita.cms.ui.assets.forms;
|
|
||||||
|
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetPane;
|
|
||||||
import com.arsdigita.cms.ui.assets.AssetSearchWidget;
|
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
|
||||||
|
|
||||||
import org.librecms.CmsConstants;
|
|
||||||
import org.librecms.assets.ExternalAudioAsset;
|
|
||||||
import org.librecms.assets.LegalMetadata;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
|
|
||||||
*/
|
|
||||||
public class ExternalAudioAssetForm
|
|
||||||
extends AbstractBookmarkForm<ExternalAudioAsset> {
|
|
||||||
|
|
||||||
private AssetSearchWidget assetSearchWidget;
|
|
||||||
|
|
||||||
public ExternalAudioAssetForm(final AssetPane assetPane) {
|
|
||||||
super(assetPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addWidgets() {
|
|
||||||
super.addWidgets();
|
|
||||||
|
|
||||||
add(new Label(new GlobalizedMessage(
|
|
||||||
"cms.ui.assets.external_audio_asset.legal_metadata.label",
|
|
||||||
CmsConstants.CMS_BUNDLE)));
|
|
||||||
assetSearchWidget = new AssetSearchWidget("legal-metadata",
|
|
||||||
LegalMetadata.class);
|
|
||||||
add(assetSearchWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initForm(final PageState state,
|
|
||||||
final Map<String, Object> data) {
|
|
||||||
|
|
||||||
super.initForm(state, data);
|
|
||||||
|
|
||||||
final Long selectedAssetId = getSelectedAssetId(state);
|
|
||||||
|
|
||||||
if (selectedAssetId != null) {
|
|
||||||
|
|
||||||
if (data.containsKey(
|
|
||||||
ExternalAudioAssetFormController.LEGAL_METADATA_ID)) {
|
|
||||||
|
|
||||||
final long legalMetadataId = (long) data
|
|
||||||
.get(ExternalAudioAssetFormController.LEGAL_METADATA_ID);
|
|
||||||
|
|
||||||
assetSearchWidget.setValue(state, legalMetadataId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<ExternalAudioAsset> getAssetClass() {
|
|
||||||
return ExternalAudioAsset.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> collectData(final FormSectionEvent event)
|
|
||||||
throws FormProcessException {
|
|
||||||
|
|
||||||
final PageState state = event.getPageState();
|
|
||||||
|
|
||||||
final Map<String, Object> data = new HashMap<>();
|
|
||||||
if (assetSearchWidget.getValue(state) != null) {
|
|
||||||
|
|
||||||
data.put(ExternalAudioAssetFormController.LEGAL_METADATA_ID,
|
|
||||||
assetSearchWidget.getValue(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue