Skip to content
Snippets Groups Projects
Commit 946ae9d2 authored by buczekp's avatar buczekp
Browse files

[LMS-789] added external links with simple regexp checking

SVN: 10601
parent 2c6d2531
No related branches found
No related tags found
No related merge requests found
Showing
with 380 additions and 24 deletions
......@@ -21,6 +21,8 @@ import java.util.List;
import com.extjs.gxt.ui.client.data.ModelData;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer.AbstractPropertyColRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.experiment.CommonExperimentColDefKind;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.experiment.PropertyExperimentColDef;
......@@ -42,18 +44,21 @@ public final class ExperimentModel extends BaseEntityModel<Experiment>
public ExperimentModel(final Experiment entity)
{
super(entity, createColumnsSchema(entity));
super(entity, createColumnsSchemaForRendering(entity));
}
// here we create the columns definition having just one table row. We need them only to render
// column values (headers have been already created), so no message provider is needed.
private static List<IColumnDefinitionUI<Experiment>> createColumnsSchema(Experiment entity)
private static List<IColumnDefinitionUI<Experiment>> createColumnsSchemaForRendering(
Experiment entity)
{
List<IColumnDefinitionUI<Experiment>> list = createCommonColumnsSchema(null);
for (ExperimentProperty prop : entity.getProperties())
{
ExperimentTypePropertyType etpt = prop.getEntityTypePropertyType();
list.add(new PropertyExperimentColDef(etpt.getPropertyType()));
AbstractPropertyColDef<Experiment> colDef =
new PropertyExperimentColDef(etpt.getPropertyType());
list.add(AbstractPropertyColRenderer.getPropertyColRenderer(colDef));
}
return list;
}
......
......@@ -21,6 +21,8 @@ import java.util.List;
import com.extjs.gxt.ui.client.data.ModelData;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer.AbstractPropertyColRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.material.CommonMaterialColDefKind;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.material.PropertyMaterialColDef;
......@@ -42,18 +44,21 @@ public final class MaterialModel extends BaseEntityModel<Material>
public MaterialModel(final Material entity)
{
super(entity, createColumnsSchema(entity));
super(entity, createColumnsSchemaForRendering(entity));
}
// here we create the columns definition having just one table row. We need them only to render
// column values (headers have been already created), so no message provider is needed.
private static List<IColumnDefinitionUI<Material>> createColumnsSchema(Material entity)
private static List<IColumnDefinitionUI<Material>> createColumnsSchemaForRendering(
Material entity)
{
List<IColumnDefinitionUI<Material>> list = createCommonColumnsSchema(null);
for (MaterialProperty prop : entity.getProperties())
{
MaterialTypePropertyType etpt = prop.getEntityTypePropertyType();
list.add(new PropertyMaterialColDef(etpt.getPropertyType()));
AbstractPropertyColDef<Material> colDef =
new PropertyMaterialColDef(etpt.getPropertyType());
list.add(AbstractPropertyColRenderer.getPropertyColRenderer(colDef));
}
return list;
}
......
......@@ -22,7 +22,9 @@ import java.util.List;
import com.extjs.gxt.ui.client.data.ModelData;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer.AbstractPropertyColRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.sample.CommonSampleColDefKind;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.sample.ParentContainerSampleColDef;
......@@ -47,7 +49,7 @@ public final class SampleModel extends BaseEntityModel<Sample>
public SampleModel(final Sample entity)
{
super(entity, createColumnsSchema(entity));
super(entity, createColumnsSchemaForRendering(entity));
set(ModelDataPropertyNames.SAMPLE_TYPE, entity.getSampleType() != null ? entity
.getSampleType().getCode() : null);
// add a link for experiment
......@@ -81,7 +83,7 @@ public final class SampleModel extends BaseEntityModel<Sample>
// here we create the columns definition having just one table row. We need them only to render
// column values (headers have been already created), so no message provider is needed.
private static List<IColumnDefinitionUI<Sample>> createColumnsSchema(Sample sample)
private static List<IColumnDefinitionUI<Sample>> createColumnsSchemaForRendering(Sample sample)
{
List<IColumnDefinitionUI<Sample>> list = createCommonColumnsSchema(null);
List<IColumnDefinitionUI<Sample>> parentColumns =
......@@ -90,7 +92,9 @@ public final class SampleModel extends BaseEntityModel<Sample>
for (SampleProperty prop : sample.getProperties())
{
SampleTypePropertyType etpt = prop.getEntityTypePropertyType();
list.add(new PropertySampleColDef(etpt.getPropertyType(), etpt.isDisplayed()));
AbstractPropertyColDef<Sample> colDef =
new PropertySampleColDef(etpt.getPropertyType(), etpt.isDisplayed());
list.add(AbstractPropertyColRenderer.getPropertyColRenderer(colDef));
}
return list;
}
......
/*
* Copyright 2009 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
/**
* An abstract decorator for {@link AbstractPropertyColDef} to be used in grids for rendering values
* in a different way in grids than in export. <br>
* It changes {@link AbstractPropertyColDef#getValue(Object)} behavior distinguishing certain
* property types so in grid there can be e.g. a link displayed for hyperlink property. Other
* methods are delegated without any change.
*
* @author Piotr Buczek
*/
public abstract class AbstractPropertyColRenderer<T> implements IColumnDefinitionUI<T>
{
/**
* @return property renderer for given column of given entity
*/
public static <S> AbstractPropertyColRenderer<S> getPropertyColRenderer(
AbstractPropertyColDef<S> colDef)
{
switch (colDef.getDataTypeCode())
{
case HYPERLINK:
return new HyperlinkPropertyColRenderer<S>(colDef);
default:
return new DefaultPropertyColRenderer<S>(colDef);
}
}
protected final AbstractPropertyColDef<T> colDef;
public AbstractPropertyColRenderer(AbstractPropertyColDef<T> colDef)
{
super();
this.colDef = colDef;
}
public String getValue(T entity)
{
return renderValue(colDef.getValue(entity));
}
/** @return given <var>value</var> rendered depending on property type */
protected abstract String renderValue(String value);
// default delegate methods
public String getHeader()
{
return colDef.getHeader();
}
public String getIdentifier()
{
return colDef.getIdentifier();
}
public int getWidth()
{
return colDef.getWidth();
}
public boolean isHidden()
{
return colDef.isHidden();
}
public DataTypeCode getDataTypeCode()
{
return colDef.getDataTypeCode();
}
}
/*
* Copyright 2009 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
/**
* An {@link AbstractPropertyColRenderer} which renders value in a default way (as a simple String).
*
* @author Piotr Buczek
*/
class DefaultPropertyColRenderer<T> extends AbstractPropertyColRenderer<T>
{
public DefaultPropertyColRenderer(AbstractPropertyColDef<T> colDef)
{
super(colDef);
}
@Override
protected String renderValue(String value)
{
return value;
}
}
/*
* Copyright 2009 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractPropertyColDef;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ExternalHyperlink;
/**
* An {@link AbstractPropertyColRenderer} which renders value as an external hyperlink.
*
* @author Piotr Buczek
*/
class HyperlinkPropertyColRenderer<T> extends AbstractPropertyColRenderer<T>
{
public HyperlinkPropertyColRenderer(AbstractPropertyColDef<T> colDef)
{
super(colDef);
}
@Override
protected String renderValue(String value)
{
return ExternalHyperlink.createAnchorString(value, value);
}
}
......@@ -31,6 +31,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listene
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.AbstractPropertyValueRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.AbstractSimplePropertyValueRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property.IPropertyValueRenderer;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ExternalHyperlink;
import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IEntityInformationHolder;
......@@ -282,15 +283,22 @@ public final class PropertyValueRenderers
public Widget getAsWidget(T object)
{
if (isMaterialProperty(object))
switch (getDataTypeCode(object))
{
return createLinkToMaterial(object);
} else
{
return new InlineHTML(object.getValue());
case MATERIAL:
return createLinkToMaterial(object);
case HYPERLINK:
return createHyperlink(object);
default:
return createHtmlWidget(object);
}
}
private DataTypeCode getDataTypeCode(T property)
{
return getPropertyType(property).getDataType().getCode();
}
private Widget createLinkToMaterial(T object)
{
String value = object.getValue();
......@@ -319,9 +327,15 @@ public final class PropertyValueRenderers
return panel;
}
private boolean isMaterialProperty(T property)
private Widget createHtmlWidget(T object)
{
return getPropertyType(property).getDataType().getCode().equals(DataTypeCode.MATERIAL);
return new InlineHTML(object.getValue());
}
private Widget createHyperlink(T object)
{
String value = object.getValue();
return new ExternalHyperlink(value, value);
}
private boolean isAllowedMaterialTypeUnspecified(T property)
......
......@@ -20,6 +20,7 @@ import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
......@@ -41,6 +42,8 @@ public abstract class AbstractPropertyColDef<T> extends AbstractColumnDefinition
private String simpleCode;
private PropertyType propertyType;
// GWT only
public AbstractPropertyColDef()
{
......@@ -55,17 +58,19 @@ public abstract class AbstractPropertyColDef<T> extends AbstractColumnDefinition
int width, String propertyTypeLabel, String identifierPrefix)
{
this(propertyType.getSimpleCode(), isDisplayedByDefault, width, propertyType
.isInternalNamespace(), propertyTypeLabel, identifierPrefix + PROPERTY_PREFIX);
.isInternalNamespace(), propertyTypeLabel, identifierPrefix + PROPERTY_PREFIX,
propertyType);
}
protected AbstractPropertyColDef(String propertyTypeCode, boolean isDisplayedByDefault,
int width, boolean isInternalNamespace, String propertyTypeLabel,
String identifierPrefix)
String identifierPrefix, PropertyType propertyType)
{
super(propertyTypeLabel, width, isDisplayedByDefault);
this.isInternalNamespace = isInternalNamespace;
this.simpleCode = propertyTypeCode;
this.identifierPrefix = identifierPrefix;
this.propertyType = propertyType;
}
@Override
......@@ -88,13 +93,19 @@ public abstract class AbstractPropertyColDef<T> extends AbstractColumnDefinition
private boolean isMatching(EntityProperty<?, ?> prop)
{
PropertyType propertyType = prop.getEntityTypePropertyType().getPropertyType();
return propertyType.isInternalNamespace() == isInternalNamespace
&& propertyType.getSimpleCode().equals(simpleCode);
PropertyType propType = prop.getEntityTypePropertyType().getPropertyType();
return propType.isInternalNamespace() == isInternalNamespace
&& propType.getSimpleCode().equals(simpleCode);
}
public String getIdentifier()
{
return identifierPrefix + isInternalNamespace + simpleCode;
}
public final DataTypeCode getDataTypeCode()
{
return propertyType.getDataType().getCode();
}
}
\ No newline at end of file
......@@ -34,7 +34,7 @@ public class PropertyExperimentColDef extends AbstractPropertyColDef<Experiment>
// GWT only
public PropertyExperimentColDef()
{
super(null, false, 0, false, null, null);
super(null, false, 0, false, null, null, null);
}
public PropertyExperimentColDef(PropertyType propertyType)
......
......@@ -34,7 +34,7 @@ public class PropertyMaterialColDef extends AbstractPropertyColDef<Material> imp
// GWT only
public PropertyMaterialColDef()
{
super(null, false, 0, false, null, null);
super(null, false, 0, false, null, null, null);
}
public PropertyMaterialColDef(PropertyType propertyType)
......
......@@ -30,7 +30,7 @@ public class PropertySampleColDef extends AbstractPropertyColDef<Sample> impleme
// GWT only
public PropertySampleColDef()
{
super(null, false, 0, false, null, null);
super(null, false, 0, false, null, null, null);
}
public PropertySampleColDef(PropertyType propertyType, boolean isDisplayedByDefault)
......
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field;
import com.extjs.gxt.ui.client.widget.form.TextField;
import ch.systemsx.cisd.openbis.generic.shared.basic.CommonValidationConstants;
/**
* A {@link TextField} extension for registering text (<code>String</code>) that will be rendered as
* a link. The text characters are validated.
*
* @author Piotr Buczek
*/
public class HyperlinkField extends VarcharField
{
public HyperlinkField(final String label, final boolean mandatory)
{
super(label, mandatory);
setRegex(CommonValidationConstants.HYPERLINK_REGEXP);
setEmptyText("Hyperlink");
getMessages().setBlankText("Hyperlink required");
getMessages().setRegexText("Hyperlink has improper format");
}
}
\ No newline at end of file
......@@ -71,6 +71,8 @@ public class PropertyFieldFactory
case MATERIAL:
return wrapUnaware(MaterialChooserField.create(label, isMandatory, pt
.getMaterialType(), originalRawValue, viewContext));
case HYPERLINK:
return wrapUnaware(new HyperlinkField(label, isMandatory));
}
throw new IllegalStateException("unknown enum " + dataType);
}
......
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget;
import com.google.gwt.user.client.ui.InlineHTML;
/**
* A {@link InlineHTML} widget extension that renders as an anchor to an external resource. <br>
* The anchor opens in a new window/tab depending on the browser.
*
* @author Piotr Buczek
*/
public final class ExternalHyperlink extends InlineHTML
{
/**
* Creates a hyperlink with its text and href specified.
*
* @param text the hyperlink's text
* @param href the hyperlink's href
*/
public ExternalHyperlink(String text, String href)
{
// using DOM.createAnchor() like in Hypelink is another way to implement this
super(createAnchorString(text, href));
}
public static String createAnchorString(String text, String href)
{
return "<a href=\"" + href + "\" target=\"_blank\">" + text + "</a>";
}
}
......@@ -33,6 +33,7 @@ import ch.systemsx.cisd.common.collections.IToStringConverter;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.common.utilities.PropertyUtils;
import ch.systemsx.cisd.common.utilities.PropertyUtils.Boolean;
import ch.systemsx.cisd.openbis.generic.shared.basic.CommonValidationConstants;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
......@@ -70,6 +71,7 @@ public final class PropertyValidator implements IPropertyValueValidator
map.put(EntityDataType.REAL, new RealValidator());
map.put(EntityDataType.CONTROLLEDVOCABULARY, new ControlledVocabularyValidator());
map.put(EntityDataType.MATERIAL, new MaterialValidator());
map.put(EntityDataType.HYPERLINK, new HyperlinkValidator());
return map;
}
......@@ -288,4 +290,25 @@ public final class PropertyValidator implements IPropertyValueValidator
return value;
}
}
private final static class HyperlinkValidator implements IDataTypeValidator
{
//
// IDataTypeValidator
//
public final String validate(final String value) throws UserFailureException
{
assert value != null : "Unspecified value.";
if (value.matches(CommonValidationConstants.HYPERLINK_REGEXP))
{
return value;
} else
{
throw UserFailureException.fromTemplate(
"Hyperlink value '%s' has improper format.", value);
}
}
}
}
/*
* Copyright 2009 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.generic.shared.basic;
/**
* Common constants to be used both on client and server side for field validation.
*
* @author Piotr Buczek
*/
public class CommonValidationConstants
{
// A complete regexp for hyperlink may be very complex like this one:
// http://internet.ls-la.net/folklore/url-regexpr.html
// We should rather use sth simple for "safe" hyperlink - with no <>()[]
/** a simple regular expression for "safe" hyperlinks */
public static final String HYPERLINK_REGEXP = "[^<>()\\[\\]]*";
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment