blob: 4aaccf9f0f32f4ec99b325d9a42330a718233534 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.sling.servlets.post.impl.helper;
import java.util.ArrayList;
import java.util.List;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.servlets.post.SlingPostConstants;
/**
* Encapsulates all infos from the respective request parameters that are needed
* to create the repository property
*/
public class RequestProperty {
private static final RequestParameter[] EMPTY_PARAM_ARRAY = new RequestParameter[0];
public static final String DEFAULT_IGNORE = SlingPostConstants.RP_PREFIX
+ "ignore";
public static final String DEFAULT_NULL = SlingPostConstants.RP_PREFIX
+ "null";
private final String path;
private final String name;
private final String parentPath;
private RequestParameter[] values;
private String[] stringValues;
private String typeHint;
private boolean hasMultiValueTypeHint;
private RequestParameter[] defaultValues = EMPTY_PARAM_ARRAY;
private boolean isDelete;
private String repositoryResourcePath;
private boolean isRepositoryResourceMove;
private boolean ignoreBlanks;
private boolean useDefaultWhenMissing;
private boolean patch = false;
private Chunk chunk;
public RequestProperty(String path) {
assert path.startsWith("/");
this.path = ResourceUtil.normalize(path);
this.parentPath = ResourceUtil.getParent(path);
this.name = ResourceUtil.getName(path);
}
public String getTypeHint() {
return typeHint;
}
public boolean hasMultiValueTypeHint() {
return this.hasMultiValueTypeHint;
}
public void setTypeHintValue(String typeHint) {
if ( typeHint != null && typeHint.endsWith("[]") ) {
this.typeHint = typeHint.substring(0, typeHint.length() - 2);
this.hasMultiValueTypeHint = true;
} else {
this.typeHint = typeHint;
this.hasMultiValueTypeHint = false;
}
}
public String getPath() {
return path;
}
public String getName() {
return name;
}
public String getParentPath() {
return parentPath;
}
public boolean hasValues() {
if (useDefaultWhenMissing && defaultValues != null && defaultValues.length > 0) {
return true;
} else {
if (ignoreBlanks) {
return (values != null && getStringValues().length > 0);
} else {
return values != null;
}
}
}
public RequestParameter[] getValues() {
return values;
}
public void setValues(RequestParameter[] values) {
this.values = values;
}
public RequestParameter[] getDefaultValues() {
return defaultValues;
}
public void setDefaultValues(RequestParameter[] defaultValues) {
if (defaultValues == null) {
this.defaultValues = EMPTY_PARAM_ARRAY;
} else {
this.defaultValues = defaultValues;
}
}
public boolean isFileUpload() {
return values != null && !values[0].isFormField();
}
/**
* Checks if this property provides any values. this is the case if one of
* the values is not empty or if the default handling is not 'ignore'
*
* @return <code>true</code> if this property provides values
*/
public boolean providesValue() {
// should void double creation of string values
String[] sv = getStringValues();
if (sv == null) {
// is missleading return type. but means that property should not
// get auto-create values
return true;
}
for (String s : sv) {
if (!s.equals("")) {
return true;
}
}
return false;
}
/**
* Returns the assembled string array out of the provided request values and
* default values.
*
* @return a String array or <code>null</code> if the property needs to be
* removed.
*/
public String[] getStringValues() {
if (stringValues == null) {
if (values == null && useDefaultWhenMissing) {
stringValues = new String[] { defaultValues[0].getString() };
} else if (values.length > 1) {
// TODO: how the default values work for MV props is not very
// clear
List<String> stringValueList = new ArrayList<String>(values.length);
for (int i = 0; i < values.length; i++) {
String value = values[i].getString();
if ((!ignoreBlanks) || value.length() > 0) {
stringValueList.add(value);
}
}
stringValues = stringValueList.toArray(new String[stringValueList.size()]);
} else {
String value = values[0].getString();
if (value.equals("")) {
if (ignoreBlanks) {
return new String[0];
} else {
if (defaultValues.length == 1) {
String defValue = defaultValues[0].getString();
if (defValue.equals(DEFAULT_IGNORE)) {
// ignore means, do not create empty values
return new String[0];
} else if (defValue.equals(DEFAULT_NULL)) {
// null means, remove property if exist
return null;
}
value = defValue;
}
}
}
stringValues = new String[] { value };
}
}
return stringValues;
}
/**
* Specifies whether this property should be deleted before any new content
* is to be set according to the values stored.
*
* @param isDelete <code>true</code> if the repository item described by
* this is to be deleted before any other operation.
*/
public void setDelete(boolean isDelete) {
this.isDelete = isDelete;
}
/**
* Determine the deletion status of this item
* @return <code>true</code> if the repository item described by this is
* to be deleted before setting new content to it.
*/
public boolean isDelete() {
return isDelete;
}
/**
* Sets the path of the repository item from which the content for this
* property is to be copied or moved. The path may be relative in which case
* it will be resolved relative to the absolute path of this property.
*
* @param sourcePath The path of the repository item to get the content from
* @param isMove <code>true</code> if the source content is to be moved,
* otherwise the source content is copied from the repository
* item.
*/
public void setRepositorySource(String sourcePath, boolean isMove) {
// make source path absolute
if (!sourcePath.startsWith("/")) {
sourcePath = getParentPath() + "/" + sourcePath;
sourcePath = ResourceUtil.normalize(sourcePath);
}
this.repositoryResourcePath = sourcePath;
this.isRepositoryResourceMove = isMove;
}
/**
* If this is a target of a move operation
* @return <code>true</code> if the content of this property is to be set
* by moving content from another repository item.
*
* @see #getRepositorySource()
*/
public boolean hasRepositoryMoveSource() {
return isRepositoryResourceMove;
}
/**
* if this is the source of a copy action
* @return <code>true</code> if the content of this property is to be set
* by copying content from another repository item.
*
* @see #getRepositorySource()
*/
public boolean hasRepositoryCopySource() {
return getRepositorySource() != null && !hasRepositoryMoveSource();
}
/**
* get the source of a copy or move operation
* @return the absolute path of the repository item from which the content
* for this property is to be copied or moved.
*
* @see #hasRepositoryCopySource()
* @see #hasRepositoryMoveSource()
* @see #setRepositorySource(String, boolean)
*/
public String getRepositorySource() {
return repositoryResourcePath;
}
public void setIgnoreBlanks(boolean b) {
ignoreBlanks = b;
}
public void setUseDefaultWhenMissing(boolean b) {
useDefaultWhenMissing = b;
}
public void setPatch(boolean b) {
patch = b;
}
/**
* determines if this property is handled as multi-value property
* @return whether this property is to be handled as a multi-value property
* seen as set.
*/
public boolean isPatch() {
return patch;
}
/**
* it this is a chunk upload?
* @return true if request is chunk upload.
*/
public boolean isChunkUpload() {
return chunk != null;
}
public Chunk getChunk() {
return chunk;
}
public void setChunk(Chunk chunk) {
this.chunk = chunk;
}
}