/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.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.gnu.org/licenses/agpl.txt * * 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 se.streamsource.streamflow.web.context.administration.forms.definition; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.txt.UniversalEncodingDetector; import org.qi4j.api.common.Optional; import org.qi4j.api.constraint.ConstraintViolationException; import org.qi4j.api.constraint.Name; import org.qi4j.api.entity.EntityReference; import org.qi4j.api.entity.Identity; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.specification.Specification; import org.qi4j.api.structure.Module; import org.qi4j.api.unitofwork.UnitOfWork; import org.qi4j.api.util.Iterables; import org.qi4j.api.value.ValueBuilder; import org.qi4j.library.constraints.annotation.MaxLength; import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.resource.ResourceException; import se.streamsource.dci.api.Context; import se.streamsource.dci.api.DeleteContext; import se.streamsource.dci.api.IndexContext; import se.streamsource.dci.api.Requires; import se.streamsource.dci.api.RoleMap; import se.streamsource.dci.value.EntityValue; import se.streamsource.dci.value.link.LinkValue; import se.streamsource.dci.value.link.LinksValue; import se.streamsource.streamflow.api.administration.form.AttachmentFieldValue; import se.streamsource.streamflow.api.administration.form.CommentFieldValue; import se.streamsource.streamflow.api.administration.form.FieldDefinitionAdminValue; import se.streamsource.streamflow.api.administration.form.FieldGroupFieldValue; import se.streamsource.streamflow.api.administration.form.FieldValue; import se.streamsource.streamflow.api.administration.form.GeoLocationFieldValue; import se.streamsource.streamflow.api.administration.form.NumberFieldValue; import se.streamsource.streamflow.api.administration.form.OpenSelectionFieldValue; import se.streamsource.streamflow.api.administration.form.SelectionFieldValue; import se.streamsource.streamflow.api.administration.form.TextAreaFieldValue; import se.streamsource.streamflow.api.administration.form.TextFieldValue; import se.streamsource.streamflow.util.Strings; import se.streamsource.streamflow.web.context.LinksBuilder; import se.streamsource.streamflow.web.domain.Describable; import se.streamsource.streamflow.web.domain.entity.form.DatatypeDefinitionEntity; import se.streamsource.streamflow.web.domain.entity.form.FieldEntity; import se.streamsource.streamflow.web.domain.structure.form.Datatype; import se.streamsource.streamflow.web.domain.structure.form.DatatypeDefinition; import se.streamsource.streamflow.web.domain.structure.form.DatatypeDefinitions; import se.streamsource.streamflow.web.domain.structure.form.Field; import se.streamsource.streamflow.web.domain.structure.form.FieldGroup; import se.streamsource.streamflow.web.domain.structure.form.FieldGroupValue; import se.streamsource.streamflow.web.domain.structure.form.FieldId; import se.streamsource.streamflow.web.domain.structure.form.FieldValueDefinition; import se.streamsource.streamflow.web.domain.structure.form.Fields; import se.streamsource.streamflow.web.domain.structure.form.Mandatory; import se.streamsource.streamflow.web.domain.structure.form.Statistical; /** * JAVADOC */ @Mixins(FormFieldContext.Mixin.class) public interface FormFieldContext extends DeleteContext, IndexContext<FieldDefinitionAdminValue>, Context { public LinksValue possibledatatypes(); public void changedescription( @Optional @MaxLength(100) @Name("description") String description ); public void changemandatory( @Name("mandatory") boolean mandatory ); public void changefieldid( @Name("id") String id ); public void changedatatype( @Name("datatype") EntityValue dto); public void changehint( @Optional @Name("hint") String hint ); @Requires(TextFieldValue.class) public void changewidth( @Name("width") int newWidth ); @Requires(TextFieldValue.class) public void changeregularexpression( @Optional @Name("expression") String regularExpression ); @Requires(TextAreaFieldValue.class) public void changerows( @Name("rows") int newRows ); @Requires(TextAreaFieldValue.class) public void changecols( @Name("columns") int newRows ); @Requires(NumberFieldValue.class) public void changeinteger( @Name("integer") boolean isInteger ); @Requires(SelectionFieldValue.class) public void addselectionelement( @Name("selection") String name ); @Requires(SelectionFieldValue.class) public void removeselectionelement( @Name("index") int index ); @Requires(SelectionFieldValue.class) public void moveselectionelement( @Name("name") String name, @Name("index") int index); @Requires(SelectionFieldValue.class) public void changeselectionelementname( @Name("name") String name, @Name("index") int index ); @Requires(OpenSelectionFieldValue.class) public void changeopenselectionname( @Name("name") String name ); @Requires(SelectionFieldValue.class) public void removeallselectionelements(); public void move( @Name("direction") String direction ); @FirstFieldInFirstPage(false) public LinksValue possiblerulefields(); @Requires(SelectionFieldValue.class) public void importvalues( Representation representation ); @Requires(GeoLocationFieldValue.class) public void changepoint( @Name("point") boolean point); @Requires(GeoLocationFieldValue.class) public void changepolyline( @Name("polyline") boolean polyline); @Requires(GeoLocationFieldValue.class) public void changepolygon( @Name("polygon") boolean polygon); public void changestatistical( @Name("statistical") boolean statistical ); abstract class Mixin implements FormFieldContext { @Structure Module module; public FieldDefinitionAdminValue index() { FieldEntity fieldEntity = RoleMap.role( FieldEntity.class ); ValueBuilder<FieldDefinitionAdminValue> builder = module.valueBuilderFactory().newValueBuilder( FieldDefinitionAdminValue.class ); builder.prototype().field().set( EntityReference.getEntityReference( fieldEntity ) ); builder.prototype().note().set( fieldEntity.note().get() ); builder.prototype().description().set( fieldEntity.description().get() ); builder.prototype().fieldId().set( fieldEntity.fieldId().get() ); if (fieldEntity.datatype().get() != null) { ValueBuilder<LinkValue> linkValueBuilder = module.valueBuilderFactory().newValueBuilder( LinkValue.class ); linkValueBuilder.prototype().href().set( fieldEntity.datatype().get().getUrl() ); linkValueBuilder.prototype().text().set( fieldEntity.datatype().get().getDescription() ); linkValueBuilder.prototype().id().set(EntityReference.getEntityReference( fieldEntity.datatype().get()).identity() ); linkValueBuilder.prototype().rel().set( "datatype" ); builder.prototype().datatype().set( linkValueBuilder.newInstance()); } if (fieldEntity.fieldValue().get() instanceof FieldGroupFieldValue) { ValueBuilder<LinkValue> linkValueBuilder = module.valueBuilderFactory().newValueBuilder( LinkValue.class ); FieldGroup fieldGroup = module.unitOfWorkFactory().currentUnitOfWork().get( FieldGroup.class, ((FieldGroupFieldValue) fieldEntity.fieldValue().get()).fieldGroup().get().identity()); linkValueBuilder.prototype().href().set( "" ); linkValueBuilder.prototype().text().set( fieldGroup.getDescription()); linkValueBuilder.prototype().id().set(EntityReference.getEntityReference( fieldGroup ).identity()); linkValueBuilder.prototype().rel().set( "fieldgroup" ); builder.prototype().fieldgroup().set( linkValueBuilder.newInstance()); } builder.prototype().fieldValue().set( fieldEntity.fieldValue().get() ); builder.prototype().mandatory().set( fieldEntity.isMandatory() ); builder.prototype().statistical().set( fieldEntity.isStatistical() ); builder.prototype().rule().set( fieldEntity.getRule() ); return builder.newInstance(); } public LinksValue possibledatatypes() { List<DatatypeDefinition> definitions = RoleMap.role( DatatypeDefinitions.Data.class ).datatypeDefinitions().toList(); LinksBuilder builder = new LinksBuilder( module.valueBuilderFactory() ); builder.rel( "datatype" ); for (DatatypeDefinition dataTypeDefinition : definitions) { builder.addLink( dataTypeDefinition.getDescription(), EntityReference.getEntityReference( dataTypeDefinition).identity() ); } return builder.newLinks(); } public void changedescription( String description ) { Describable describable = RoleMap.role( Describable.class ); describable.changeDescription( description ); } public void changemandatory( boolean mandatory ) { Mandatory mandatoryField = RoleMap.role( Mandatory.class ); mandatoryField.changeMandatory( mandatory ); } public void changefieldid( String id ) { FieldId fieldId = RoleMap.role( FieldId.class ); fieldId.changeFieldId( id ); } public void changedatatype( EntityValue dto ) { UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork(); Datatype datatype = RoleMap.role( Datatype.class ); String entityReference = dto.entity().get(); if (entityReference != null) { DatatypeDefinitionEntity dataTypeDefinitionEntity = uow.get( DatatypeDefinitionEntity.class, entityReference ); datatype.changeDatatype( dataTypeDefinitionEntity ); } else { datatype.changeDatatype( null ); } } public void changehint( String hint ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); TextFieldValue value = RoleMap.role( TextFieldValue.class ); ValueBuilder<TextFieldValue> builder = value.buildWith(); builder.prototype().hint().set( hint ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changewidth( int newWidth ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); TextFieldValue value = RoleMap.role( TextFieldValue.class ); ValueBuilder<TextFieldValue> builder = value.buildWith(); builder.prototype().width().set( newWidth ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changeregularexpression( String regularExpression ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); TextFieldValue value = RoleMap.role( TextFieldValue.class ); ValueBuilder<TextFieldValue> builder = value.buildWith(); builder.prototype().regularExpression().set( regularExpression ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changerows( int newRows ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); TextAreaFieldValue value = RoleMap.role( TextAreaFieldValue.class ); ValueBuilder<TextAreaFieldValue> builder = value.buildWith(); builder.prototype().rows().set( newRows ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changecols( int newCols ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); TextAreaFieldValue value = RoleMap.role( TextAreaFieldValue.class ); ValueBuilder<TextAreaFieldValue> builder = value.buildWith(); builder.prototype().cols().set( newCols ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changeinteger( boolean isInteger ) { FieldValueDefinition definition = RoleMap.role( FieldValueDefinition.class ); NumberFieldValue value = RoleMap.role( NumberFieldValue.class ); ValueBuilder<NumberFieldValue> builder = value.buildWith(); builder.prototype().integer().set( isInteger ); definition.changeFieldValue( builder.newInstance() ); } public void addselectionelement( String name ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); builder.prototype().values().get().add( name ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void removeselectionelement( int index ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); if (builder.prototype().values().get().size() > index) { builder.prototype().values().get().remove( index ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } } public void removeallselectionelements() { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); builder.prototype().values().get().clear(); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void moveselectionelement( String name, int index ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); String element = builder.prototype().values().get().remove( index ); if ("up".equals( name )) { builder.prototype().values().get().add( index - 1, element ); } else { builder.prototype().values().get().add( index + 1, element ); } fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changeselectionelementname( String name, int index ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); builder.prototype().values().get().set( index, name ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changeopenselectionname( String name ) { FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); OpenSelectionFieldValue value = RoleMap.role( OpenSelectionFieldValue.class ); ValueBuilder<OpenSelectionFieldValue> builder = value.buildWith(); builder.prototype().openSelectionName().set( name ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void move( String direction ) { Field field = RoleMap.role( Field.class ); Fields fields = RoleMap.role( Fields.class ); Fields.Data fieldsData = RoleMap.role( Fields.Data.class ); int index = fieldsData.fields().toList().indexOf( field ); if (direction.equalsIgnoreCase( "up" )) { try { fields.moveField( field, index - 1 ); } catch (ConstraintViolationException e) { } } else { fields.moveField( field, index + 1 ); } } public void delete() { Field field = RoleMap.role( Field.class ); Fields fields = RoleMap.role( Fields.class ); fields.removeField( field ); } public LinksValue possiblerulefields() { final Fields.Data fields = RoleMap.role( Fields.Data.class ); Field field = RoleMap.role( Field.class ); /*final Pages.Data pages = RoleMap.role( Pages.Data.class ); Page page = RoleMap.role( Page.class ); final int pageIndex = pages.pages().toList().indexOf( page ); Iterable<Field> possiblePagefields = Iterables.filter( new Specification<Field>() { public boolean satisfiedBy( Field field ) { FieldValue fieldValue = ((FieldValueDefinition.Data) field).fieldValue().get(); boolean filter = fieldValue instanceof FieldGroupValue || fieldValue instanceof CommentFieldValue || fieldValue instanceof TextAreaFieldValue || fieldValue instanceof AttachmentFieldValue; return !filter; } }, Iterables.flatten( Iterables.map( new Function<Page, Iterable<Field>>() { public Iterable<Field> map( Page page ) { return ((Fields.Data) page).fields().toList(); } }, Iterables.filter( new Specification<Page>() { public boolean satisfiedBy( Page page ) { return pages.pages().toList().indexOf( page ) < pageIndex; } }, pages.pages() ) ) ) ); */ final int index = fields.fields().toList().indexOf( field ); Iterable<Field> possiblefields = Iterables.filter( new Specification<Field>() { public boolean satisfiedBy( Field field ) { FieldValue fieldValue = ((FieldValueDefinition.Data) field).fieldValue().get(); boolean filter = fieldValue instanceof FieldGroupValue || fieldValue instanceof CommentFieldValue || fieldValue instanceof TextAreaFieldValue || fieldValue instanceof AttachmentFieldValue; return fields.fields().toList().indexOf( field ) < index && !filter ; } },fields.fields() ); LinksBuilder builder = new LinksBuilder( module.valueBuilderFactory() ); builder.addLink( " ", "" ); /* for( Field f : possiblePagefields ) { builder.addLink( f.getDescription() + "-" + f.getFieldId(), ((Identity) f).identity().get() ); } */ for( Field f : possiblefields ) { builder.addLink( f.getDescription() + "-" + f.getFieldId(), ((Identity) f).identity().get() ); } return builder.newLinks(); } public void changepoint( boolean point){ FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); GeoLocationFieldValue value = RoleMap.role( GeoLocationFieldValue.class ); ValueBuilder<GeoLocationFieldValue> builder = value.buildWith(); builder.prototype().point().set( point ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changepolyline( boolean polyline){ FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); GeoLocationFieldValue value = RoleMap.role( GeoLocationFieldValue.class ); ValueBuilder<GeoLocationFieldValue> builder = value.buildWith(); builder.prototype().polyline().set( polyline ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changepolygon( boolean polygon){ FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); GeoLocationFieldValue value = RoleMap.role( GeoLocationFieldValue.class ); ValueBuilder<GeoLocationFieldValue> builder = value.buildWith(); builder.prototype().polygon().set( polygon ); fieldValueDefinition.changeFieldValue( builder.newInstance() ); } public void changestatistical( boolean statistical ) { Statistical statisticalField = RoleMap.role( Statistical.class ); statisticalField.changeStatistical( statistical ); } public void importvalues(Representation representation) { boolean hasChanged = false; FieldValueDefinition fieldValueDefinition = RoleMap.role( FieldValueDefinition.class ); SelectionFieldValue value = RoleMap.role( SelectionFieldValue.class ); ValueBuilder<SelectionFieldValue> builder = value.buildWith(); try { List<String> values = new ArrayList<String>(); if (representation.getMediaType().equals( MediaType.APPLICATION_EXCEL )) { HSSFWorkbook workbook = new HSSFWorkbook( representation.getStream() ); //extract a user list Sheet sheet1 = workbook.getSheetAt( 0 ); for (Row row : sheet1) { values.add( row.getCell( 0 ).getStringCellValue() ); } } else if (representation.getMediaType().equals( MediaType.TEXT_CSV )) { UniversalEncodingDetector encodingDetector = new UniversalEncodingDetector(); BufferedInputStream input = new BufferedInputStream( representation.getStream() ); Charset detect = encodingDetector.detect( input, new Metadata() ); BufferedReader bufReader = new BufferedReader( new InputStreamReader( input, detect.name() ) ); String line; while ((line = bufReader.readLine()) != null) { if( !Strings.empty( line )) values.add( line ); } } else { throw new ResourceException( Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE ); } for( String string : values ) { if( !builder.prototype().values().get().contains( string ) ) { builder.prototype().values().get().add( string ); hasChanged = true; } } if( hasChanged ) { fieldValueDefinition.changeFieldValue( builder.newInstance() ); } } catch (IOException ioe) { throw new ResourceException( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY ); } } } }