Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit e1e6508fec
1095 changed files with 230566 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service;
import java.util.Collection;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
/**
* This interface represents service meta-data.
*
* @author David Caruana
*/
public interface ServiceDescriptor
{
/**
* @return the qualified name of the service
*/
public QName getQualifiedName();
/**
* @return the service description
*/
public String getDescription();
/**
* @return the service interface class description
*/
public Class getInterface();
/**
* @return the names of the protocols supported
*/
public Collection<String> getSupportedStoreProtocols();
/**
* @return the Store Refs of the stores supported
*/
public Collection<StoreRef> getSupportedStores();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service;
/**
* Base Exception of Service Exceptions.
*
* @author David Caruana
*/
public class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 3257008761007847733L;
public ServiceException(String msg)
{
super(msg);
}
public ServiceException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service;
import java.util.Collection;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.ImporterService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
/**
* This interface represents the registry of public Repository Services.
* The registry provides meta-data about each service and provides
* access to the service interface.
*
* @author David Caruana
*/
public interface ServiceRegistry
{
// Service Bean Names
static final String SERVICE_REGISTRY = "ServiceRegistry";
static final QName REGISTRY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ServiceRegistry");
static final QName DESCRIPTOR_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DescriptorService");
static final QName TRANSACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TransactionService");
static final QName AUTHENTICATION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthenticationService");
static final QName NAMESPACE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NamespaceService");
static final QName DICTIONARY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DictionaryService");
static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService");
static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService");
static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService");
static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService");
static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService");
static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService");
static final QName LOCK_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "LockService");
static final QName VERSION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "VersionService");
static final QName COCI_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CheckoutCheckinService");
static final QName RULE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RuleService");
static final QName IMPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ImporterService");
static final QName EXPORTER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ExporterService");
static final QName ACTION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ActionService");
static final QName PERMISSIONS_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "PermissionService");
static final QName AUTHORITY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "AuthorityService");
static final QName TEMPLATE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "TemplateService");
static final QName FILE_FOLDER_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "FileFolderService");
/**
* Get the list of services provided by the Repository
*
* @return list of provided Services
*/
Collection<QName> getServices();
/**
* Is the specified service provided by the Repository?
*
* @param service name of service to test provision of
* @return true => provided, false => not provided
*/
boolean isServiceProvided(QName service);
/**
* Get meta-data about the specified service
*
* @param service name of service to retrieve meta data for
* @return the service meta data
*/
ServiceDescriptor getServiceDescriptor(QName service);
/**
* Get the specified service.
*
* @param service name of service to retrieve
* @return the service interface (must cast to interface as described in service meta-data)
*/
Object getService(QName service);
/**
* @return the descriptor service
*/
DescriptorService getDescriptorService();
/**
* @return the transaction service
*/
TransactionService getTransactionService();
/**
* @return the namespace service (or null, if one is not provided)
*/
NamespaceService getNamespaceService();
/**
* @return the authentication service (or null, if one is not provided)
*/
AuthenticationService getAuthenticationService();
/**
* @return the node service (or null, if one is not provided)
*/
NodeService getNodeService();
/**
* @return the content service (or null, if one is not provided)
*/
ContentService getContentService();
/**
* @return the mimetype service (or null, if one is not provided)
*/
MimetypeService getMimetypeService();
/**
* @return the search service (or null, if one is not provided)
*/
SearchService getSearchService();
/**
* @return the version service (or null, if one is not provided)
*/
VersionService getVersionService();
/**
* @return the lock service (or null, if one is not provided)
*/
LockService getLockService();
/**
* @return the dictionary service (or null, if one is not provided)
*/
DictionaryService getDictionaryService();
/**
* @return the copy service (or null, if one is not provided)
*/
CopyService getCopyService();
/**
* @return the checkout / checkin service (or null, if one is not provided)
*/
CheckOutCheckInService getCheckOutCheckInService();
/**
* @return the category service (or null, if one is not provided)
*/
CategoryService getCategoryService();
/**
* @return the importer service or null if not present
*/
ImporterService getImporterService();
/**
* @return the exporter service or null if not present
*/
ExporterService getExporterService();
/**
* @return the rule service (or null, if one is not provided)
*/
RuleService getRuleService();
/**
* @return the action service (or null if one is not provided)
*/
ActionService getActionService();
/**
* @return the permission service (or null if one is not provided)
*/
PermissionService getPermissionService();
/**
* @return the authority service (or null if one is not provided)
*/
AuthorityService getAuthorityService();
/**
* @return the template service (or null if one is not provided)
*/
TemplateService getTemplateService();
/**
* @return the file-folder manipulation service (or null if one is not provided)
*/
FileFolderService getFileFolderService();
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.util.Date;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* The rule action interface
*
* @author Roy Wetherall
*/
public interface Action extends ParameterizedItem
{
/**
* Get the name of the action definition that relates to this action
*
* @return the action defintion name
*/
String getActionDefinitionName();
/**
* Get the title of the action
*
* @return the title of the action
*/
String getTitle();
/**
* Set the title of the action
*
* @param title the title of the action
*/
void setTitle(String title);
/**
* Get the description of the action
*
* @return the description of the action
*/
String getDescription();
/**
* Set the description of the action
*
* @param description the description of the action
*/
void setDescription(String description);
/**
* Get the node reference of the node that 'owns' this action.
* <p>
* The node that 'owns' the action is th one that stores it via its
* actionable aspect association.
*
* @return node reference
*/
NodeRef getOwningNodeRef();
/**
* Gets a value indicating whether the action should be executed asychronously or not.
* <p>
* The default is to execute the action synchronously.
*
* @return true if the action is executed asychronously, false otherwise.
*/
boolean getExecuteAsychronously();
/**
* Set the value that indicates whether the action should be executed asychronously or not.
*
* @param executeAsynchronously true if the action is to be executed asychronously, false otherwise.
*/
void setExecuteAsynchronously(boolean executeAsynchronously);
/**
* Get the compensating action.
* <p>
* This action is executed if the failure behaviour is to compensate and the action being executed
* fails.
*
* @return the compensating action
*/
Action getCompensatingAction();
/**
* Set the compensating action.
*
* @param action the compensating action
*/
void setCompensatingAction(Action action);
/**
* Get the date the action was created
*
* @return action creation date
*/
Date getCreatedDate();
/**
* Get the name of the user that created the action
*
* @return user name
*/
String getCreator();
/**
* Get the date that the action was last modified
*
* @return aciton modification date
*/
Date getModifiedDate();
/**
* Get the name of the user that last modified the action
*
* @return user name
*/
String getModifier();
/**
* Indicates whether the action has any conditions specified
*
* @return true if the action has any conditions specified, flase otherwise
*/
boolean hasActionConditions();
/**
* Gets the index of an action condition
*
* @param actionCondition the action condition
* @return the index
*/
int indexOfActionCondition(ActionCondition actionCondition);
/**
* Gets a list of the action conditions for this action
*
* @return list of action conditions
*/
List<ActionCondition> getActionConditions();
/**
* Get the action condition at a given index
*
* @param index the index
* @return the action condition
*/
ActionCondition getActionCondition(int index);
/**
* Add an action condition to the action
*
* @param actionCondition an action condition
*/
void addActionCondition(ActionCondition actionCondition);
/**
* Add an action condition at the given index
*
* @param index the index
* @param actionCondition the action condition
*/
void addActionCondition(int index, ActionCondition actionCondition);
/**
* Replaces the current action condition at the given index with the
* action condition provided.
*
* @param index the index
* @param actionCondition the action condition
*/
void setActionCondition(int index, ActionCondition actionCondition);
/**
* Removes an action condition
*
* @param actionCondition an action condition
*/
void removeActionCondition(ActionCondition actionCondition);
/**
* Removes all action conditions
*/
void removeAllActionConditions();
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
/**
* Rule condition interface
*
* @author Roy Wetherall
*/
public interface ActionCondition extends ParameterizedItem
{
/**
* Get the action condition definition name
*
* @param the action condition definition name
*/
public String getActionConditionDefinitionName();
/**
* Set whether the condition result should be inverted.
* <p>
* This is achieved by applying the NOT logical operator to the
* result.
* <p>
* The default value is false.
*
* @param invertCondition true indicates that the result of the condition
* is inverted, false otherwise.
*/
public void setInvertCondition(boolean invertCondition);
/**
* Indicates whether the condition result should be inverted.
* <p>
* This is achieved by applying the NOT logical operator to the result.
* <p>
* The default value is false.
*
* @return true indicates that the result of the condition is inverted, false
* otherwise
*/
public boolean getInvertCondition();
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
/**
* Rule condition interface
*
* @author Roy Wetherall
*/
public interface ActionConditionDefinition extends ParameterizedItemDefinition
{
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
/**
* Rule action interface.
*
* @author Roy Wetherall
*/
public interface ActionDefinition extends ParameterizedItemDefinition
{
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.io.Serializable;
/**
* Action execution status enumeration
*
* @author Roy Wetherall
*/
public enum ActionExecutionStatus implements Serializable
{
PENDING, // The action is queued pending execution
RUNNING, // The action is currently executing
SUCCEEDED, // The action has completed successfully
FAILED, // The action has failed
COMPENSATED // The action has failed and a compensating action has been been queued for execution
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Action service interface
*
* @author Roy Wetherall
*/
public interface ActionService
{
/**
* Get a named action definition
*
* @param name the name of the action definition
* @return the action definition
*/
ActionDefinition getActionDefinition(String name);
/**
* Get all the action definitions
*
* @return the list action definitions
*/
List<ActionDefinition> getActionDefinitions();
/**
* Get a named action condition definition
*
* @param name the name of the action condition definition
* @return the action condition definition
*/
ActionConditionDefinition getActionConditionDefinition(String name);
/**
* Get all the action condition definitions
*
* @return the list of aciton condition definitions
*/
List<ActionConditionDefinition> getActionConditionDefinitions();
/**
* Create a new action
*
* @param name the action definition name
* @return the action
*/
Action createAction(String name);
/**
* Create a new action specifying the initial set of parameter values
*
* @param name the action defintion name
* @param params the parameter values
* @return the action
*/
Action createAction(String name, Map<String, Serializable> params);
/**
* Create a composite action
*
* @return the composite action
*/
CompositeAction createCompositeAction();
/**
* Create an action condition
*
* @param name the action condition definition name
* @return the action condition
*/
ActionCondition createActionCondition(String name);
/**
* Create an action condition specifying the initial set of parameter values
*
* @param name the aciton condition definition name
* @param params the parameter valeus
* @return the action condition
*/
ActionCondition createActionCondition(String name, Map<String, Serializable> params);
/**
* The actions conditions are always checked.
*
* @see ActionService#executeAction(Action, NodeRef, boolean)
*
* @param action the action
* @param actionedUponNodeRef the actioned upon node reference
*/
void executeAction(Action action, NodeRef actionedUponNodeRef);
/**
* The action is sexecuted based on the asynchronous attribute of the action.
*
* @see ActionService#executeAction(Action, NodeRef, boolean, boolean)
*
* @param action the action
* @param actionedUponNodeRef the actioned upon node reference
* @param checkConditions indicates whether the conditions should be checked
*/
void executeAction(Action action, NodeRef actionedUponNodeRef, boolean checkConditions);
/**
* Executes the specified action upon the node reference provided.
* <p>
* If specified that the conditions should be checked then any conditions
* set on the action are evaluated.
* <p>
* If the conditions fail then the action is not executed.
* <p>
* If an action has no conditions then the action will always be executed.
* <p>
* If the conditions are not checked then the action will always be executed.
*
* @param action the action
* @param actionedUponNodeRef the actioned upon node reference
* @param checkConditions indicates whether the conditions should be checked before
* executing the action
* @param executeAsynchronously indicates whether the action should be executed asychronously or not, this value overrides
* the value set on the action its self
*/
void executeAction(Action action, NodeRef actionedUponNodeRef, boolean checkConditions, boolean executeAsynchronously);
/**
* Evaluted the conditions set on an action.
* <p>
* Returns true if the action has no conditions.
* <p>
* If the action has more than one condition their results are combined using the 'AND'
* logical operator.
*
* @param action the action
* @param actionedUponNodeRef the actioned upon node reference
* @return true if the condition succeeds, false otherwise
*/
boolean evaluateAction(Action action, NodeRef actionedUponNodeRef);
/**
* Evaluate an action condition.
*
* @param condition the action condition
* @param actionedUponNodeRef the actioned upon node reference
* @return true if the condition succeeds, false otherwise
*/
boolean evaluateActionCondition(ActionCondition condition, NodeRef actionedUponNodeRef);
/**
* Save an action against a node reference.
* <p>
* The node will be made configurable if it is not already.
* <p>
* If the action already exists then its details will be updated.
*
* @param nodeRef the node reference
* @param action the action
*/
void saveAction(NodeRef nodeRef, Action action);
/**
* Gets all the actions currently saved on the given node reference.
*
* @param nodeRef the ndoe reference
* @return the list of actions
*/
List<Action> getActions(NodeRef nodeRef);
/**
* Gets an action stored against a given node reference.
* <p>
* Returns null if the action can not be found.
*
* @param nodeRef the node reference
* @param actionId the action id
* @return the action
*/
Action getAction(NodeRef nodeRef, String actionId);
/**
* Removes an action associatied with a node reference.
*
* @param nodeRef the node reference
* @param action the action
*/
void removeAction(NodeRef nodeRef, Action action);
/**
* Removes all actions associated with a node reference
*
* @param nodeRef the node reference
*/
void removeAllActions(NodeRef nodeRef);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Rule Service Exception Class
*
* @author Roy Wetherall
*/
public class ActionServiceException extends AlfrescoRuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3257571685241467958L;
public ActionServiceException(String msgId)
{
super(msgId);
}
public ActionServiceException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public ActionServiceException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
public ActionServiceException(String msgId, Throwable cause)
{
super(msgId, cause);
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.util.List;
/**
* Composite action
*
* @author Roy Wetherall
*/
public interface CompositeAction extends Action
{
/**
* Indicates whether there are any actions
*
* @return true if there are actions, false otherwise
*/
boolean hasActions();
/**
* Add an action to the end of the list
*
* @param action the action
*/
void addAction(Action action);
/**
* Add an action to the list at the index specified
*
* @param index the index
* @param action the action
*/
void addAction(int index, Action action);
/**
* Replace the action at the specfied index with the passed action.
*
* @param index the index
* @param action the action
*/
void setAction(int index, Action action);
/**
* Gets the index of an action
*
* @param action the action
* @return the index
*/
int indexOfAction(Action action);
/**
* Get list containing the actions in their current order
*
* @return the list of actions
*/
List<Action> getActions();
/**
* Get an action at a given index
*
* @param index the index
* @return the action
*/
Action getAction(int index);
/**
* Remove an action from the list
*
* @param action the action
*/
void removeAction(Action action);
/**
* Remove all actions from the list
*/
void removeAllActions();
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import org.alfresco.service.namespace.QName;
/**
* Parameter definition interface.
*
* @author Roy Wetherall
*/
public interface ParameterDefinition
{
/**
* Get the name of the parameter.
* <p>
* This is unique and is used to identify the parameter.
*
* @return the parameter name
*/
public String getName();
/**
* Get the type of parameter
*
* @return the parameter type qname
*/
public QName getType();
/**
* Indicates whether the parameter is mandatory or not.
* <p>
* If a parameter is mandatory it means that the value can not be null.
*
* @return true if the parameter is mandatory, false otherwise
*/
public boolean isMandatory();
/**
* Get the display label of the parameter.
*
* @return the parameter display label
*/
public String getDisplayLabel();
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.io.Serializable;
import java.util.Map;
/**
* Rule item interface
*
* @author Roy Wetherall
*/
public interface ParameterizedItem
{
/**
* Unique identifier for the parameterized item
*
* @return the id string
*/
public String getId();
/**
* Get the parameter values
*
* @return get the parameter values
*/
public Map<String, Serializable> getParameterValues();
/**
* Get value of a named parameter.
*
* @param name the parameter name
* @return the value of the parameter
*/
public Serializable getParameterValue(String name);
/**
* Sets the parameter values
*
* @param parameterValues the parameter values
*/
public void setParameterValues(
Map<String, Serializable> parameterValues);
/**
* Sets the value of a parameter.
*
* @param name the parameter name
* @param value the parameter value
*/
public void setParameterValue(String name, Serializable value);
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.action;
import java.util.List;
public interface ParameterizedItemDefinition
{
/**
* Get the name of the rule item.
* <p>
* The name is unique and is used to identify the rule item.
*
* @return the name of the rule action
*/
public String getName();
/**
* The title of the parameterized item definition
*
* @return the title
*/
public String getTitle();
/**
* The description of the parameterized item definition
*
* @return the description
*/
public String getDescription();
/**
* Indicates whether the parameterized item allows adhoc properties to be set
*
* @return true if ashoc properties are allowed, false otherwise
*/
public boolean getAdhocPropertiesAllowed();
/**
* A list containing the parmameter defintions for this rule item.
*
* @return a list of parameter definitions
*/
public List<ParameterDefinition> getParameterDefinitions();
/**
* Get the parameter definition by name
*
* @param name the name of the parameter
* @return the parameter definition, null if none found
*/
public ParameterDefinition getParameterDefintion(String name);
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.coci;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Version operations service interface
*
* @author Roy Wetherall
*/
public interface CheckOutCheckInService
{
/**
* Checks out the given node placing a working copy in the destination specified.
* <p>
* When a node is checked out a read-only lock is placed on the origional node and
* a working copy is placed in the destination specified.
* <p>
* The copy aspect is applied to the working copy so that the origional node can be
* identified.
* <p>
* The working copy aspect is applied to the working copy so that it can be identified
* as the working copy of a checked out node.
* <p>
* The working copy node reference is returned to the caller.
*
* @param nodeRef a reference to the node to checkout
* @param destinationParentNodeRef the destination node reference for the working
* copy
* @param destinationAssocTypeQName the destination child assoc type for the working
* copy
* @param destinationAssocQName the destination child assoc qualified name for
* the working copy
* @return node reference to the created working copy
*/
public NodeRef checkout(
NodeRef nodeRef,
NodeRef destinationParentNodeRef,
QName destinationAssocTypeQName,
QName destinationAssocQName);
/**
* Checks out the working copy of the node into the same parent node with the same child
* associations details.
*
* @see CheckOutCheckInService#checkout(NodeRef, NodeRef, QName, QName)
*
* @param nodeRef a reference to the node to checkout
* @return a node reference to the created working copy
*/
public NodeRef checkout(NodeRef nodeRef);
/**
* Checks in the working node specified.
* <p>
* When a working copy is checked in the current state of the working copy is copyied to the
* origional node. This will include any content updated in the working node.
* <p>
* If version properties are provided the origional node will be versioned and updated accordingly.
* <p>
* If a content Url is provided it will be used to update the content of the working node before the
* checkin opertaion takes place.
* <p>
* Once the operation has completed the read lock applied to the origional node during checkout will
* be removed and the working copy of the node deleted from the repository, unless the operation is
* instructed to keep the origional node checked out. In which case the lock and the working copy will
* remain.
* <p>
* The node reference to the origional node is returned.
*
* @param workingCopyNodeRef the working copy node reference
* @param versionProperties the version properties. If null is passed then the origional node
* is NOT versioned during the checkin operation.
* @param contentUrl a content url that should be set on the working copy before
* the checkin opertation takes place. If null then the current working
* copy content is copied back to the origional node.
* @param keepCheckedOut indicates whether the node should remain checked out after the checkin
* has taken place. When the node remains checked out the working node
* reference remains the same.
* @return the node reference to the origional node, updated with the checked in
* state
*/
public NodeRef checkin(
NodeRef workingCopyNodeRef,
Map<String,Serializable> versionProperties,
String contentUrl,
boolean keepCheckedOut);
/**
* By default the checked in node is not keep checked in.
*
* @see VersionOperationsService#checkin(NodeRef, HashMap<String,Serializable>, String, boolean)
*
* @param workingCopyNodeRef the working copy node reference
* @param versionProperties the version properties. If null is passed then the origional node
* is NOT versioned during the checkin operation.
* @param contentUrl a content url that should be set on the working copy before
* the checkin opertation takes place. If null then the current working
* copy content is copied back to the origional node.
* @return the node reference to the origional node, updated with the checked in
* state
*/
public NodeRef checkin(
NodeRef workingCopyNodeRef,
Map<String, Serializable> versionProperties,
String contentUrl);
/**
* If no content url is specified then current content set on the working
* copy is understood to be current.
*
* @see VersionOperationsService#checkin(NodeRef, HashMap<String,Serializable>, String)
*
* @param workingCopyNodeRef the working copy node reference
* @param versionProperties the version properties. If null is passed then the origional node
* is NOT versioned during the checkin operation.
* @return the node reference to the origional node, updated with the checked in
* state
*/
public NodeRef checkin(
NodeRef workingCopyNodeRef,
Map<String, Serializable> versionProperties);
/**
* Cancels the checkout for a given working copy.
* <p>
* The read-only lock on the origional node is removed and the working copy is removed.
* <p>
* Note that all modification made to the working copy will be lost and the origional node
* will remiain unchanged.
* <p>
* A reference to the origional node reference is returned.
*
* @param workingCopyNodeRef the working copy node reference
* @return the origional node reference
*/
public NodeRef cancelCheckout(NodeRef workingCopyNodeRef);
/**
* Helper method to retrieve the working copy node reference for a checked out node.
* <p>
* A null node reference is returned if the node is not checked out.
*
* @param nodeRef a node reference
* @return the working copy node reference or null if none.
*/
public NodeRef getWorkingCopy(NodeRef nodeRef);
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.coci;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Version opertaions service exception class
*
* @author Roy Wetherall
*/
public class CheckOutCheckInServiceException extends AlfrescoRuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3258410621186618417L;
/**
* Constructor
*
* @param message the error message
*/
public CheckOutCheckInServiceException(String message)
{
super(message);
}
/**
* Constructor
*
* @param message the error message
* @param throwable the cause of the exeption
*/
public CheckOutCheckInServiceException(String message, Throwable throwable)
{
super(message, throwable);
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
/**
* Read-only definition of an Aspect.
*
* @author David Caruana
*/
public interface AspectDefinition extends ClassDefinition
{
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of an Association.
*
* @author David Caruana
*
*/
public interface AssociationDefinition
{
/**
* @return defining model
*/
public ModelDefinition getModel();
/**
* @return the qualified name
*/
public QName getName();
/**
* @return the human-readable title
*/
public String getTitle();
/**
* @return the human-readable description
*/
public String getDescription();
/**
* Is this a child association?
*
* @return true => child, false => general relationship
*/
public boolean isChild();
/**
* Is this association maintained by the Repository?
*
* @return true => system maintained, false => client may maintain
*/
public boolean isProtected();
/**
* @return the source class
*/
public ClassDefinition getSourceClass();
/**
* @return the role of the source class in this association?
*/
public QName getSourceRoleName();
/**
* Is the source class optional in this association?
*
* @return true => cardinality > 0
*/
public boolean isSourceMandatory();
/**
* Can there be many source class instances in this association?
*
* @return true => cardinality > 1, false => cardinality of 0 or 1
*/
public boolean isSourceMany();
/**
* @return the target class
*/
public ClassDefinition getTargetClass();
/**
* @return the role of the target class in this association?
*/
public QName getTargetRoleName();
/**
* Is the target class optional in this association?
*
* @return true => cardinality > 0
*/
public boolean isTargetMandatory();
/**
* Can there be many target class instances in this association?
*
* @return true => cardinality > 1, false => cardinality of 0 or 1
*/
public boolean isTargetMany();
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
/**
* Read-only definition of a Child Association.
*
* @author David Caruana
*
*/
public interface ChildAssociationDefinition extends AssociationDefinition
{
/**
* @return the required name of children (or null if none)
*/
public String getRequiredChildName();
/**
* @return whether duplicate child names allowed within this association?
*/
public boolean getDuplicateChildNamesAllowed();
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of a Class.
*
* @author David Caruana
*/
public interface ClassDefinition
{
/**
* @return defining model
*/
public ModelDefinition getModel();
/**
* @return the qualified name of the class
*/
public QName getName();
/**
* @return the human-readable class title
*/
public String getTitle();
/**
* @return the human-readable class description
*/
public String getDescription();
/**
* @return the super class (or null, if this is the root)
*/
public QName getParentName();
/**
* @return true => aspect, false => type
*/
public boolean isAspect();
/**
* @return the properties of the class, including inherited properties
*/
public Map<QName, PropertyDefinition> getProperties();
/**
* @return a map containing the default property values, including inherited properties
*/
public Map<QName, Serializable> getDefaultValues();
/**
* Fetch all associations for which this is a source type, including child associations.
*
* @return the associations including inherited ones
* @see ChildAssociationDefinition
*/
public Map<QName, AssociationDefinition> getAssociations();
/**
* @return true => this class supports child associations
*/
public boolean isContainer();
/**
* Fetch only child associations for which this is a source type.
*
* @return all child associations applicable to this type, including those
* inherited from super types
*/
public Map<QName, ChildAssociationDefinition> getChildAssociations();
/**
* Fetch all associations for which this is a target type, including child associations.
*
* @return the associations including inherited ones
*/
// TODO: public Map<QName, AssociationDefinition> getTargetAssociations();
/**
* @return the default aspects associated with this type
*/
public List<AspectDefinition> getDefaultAspects();
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import java.util.Locale;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of a Data Type
*
* @author David Caruana
*/
public interface DataTypeDefinition
{
//
// Built-in Property Types
//
public QName ANY = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "any");
public QName TEXT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "text");
public QName CONTENT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "content");
public QName INT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "int");
public QName LONG = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "long");
public QName FLOAT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "float");
public QName DOUBLE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "double");
public QName DATE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "date");
public QName DATETIME = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "datetime");
public QName BOOLEAN = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "boolean");
public QName QNAME = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "qname");
public QName CATEGORY = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "category");
public QName NODE_REF = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "noderef");
public QName PATH = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "path");
/**
* @return defining model
*/
public ModelDefinition getModel();
/**
* @return the qualified name of the data type
*/
public QName getName();
/**
* @return the human-readable class title
*/
public String getTitle();
/**
* @return the human-readable class description
*/
public String getDescription();
/**
* @return the indexing analyser class
*/
public String getAnalyserClassName();
/**
* @return the indexing analyser class for the specified locale
*/
public String getAnalyserClassName(Locale locale);
/**
* @return the equivalent java class name (or null, if not mapped)
*/
public String getJavaClassName();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
/**
* Base Exception of Data Dictionary Exceptions.
*
* @author David Caruana
*/
public class DictionaryException extends RuntimeException
{
private static final long serialVersionUID = 3257008761007847733L;
public DictionaryException(String msg)
{
super(msg);
}
public DictionaryException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import java.util.Collection;
import org.alfresco.service.namespace.QName;
/**
* This interface represents the Repository Data Dictionary. The
* dictionary provides access to content meta-data such as Type
* and Aspect descriptions.
*
* Content meta-data is organised into models where each model is
* given a qualified name. This means that it is safe to develop
* independent models and bring them together into the same
* Repository without name clashes (as long their namespace is
* different).
*
* @author David Caruana
*/
public interface DictionaryService
{
/**
* @return the names of all models that have been registered with the Repository
*/
public Collection<QName> getAllModels();
/**
* @param model the model name to retrieve
* @return the specified model (or null, if it doesn't exist)
*/
public ModelDefinition getModel(QName model);
/**
* @return the names of all data types that have been registered with the Repository
*/
Collection<QName> getAllDataTypes();
/**
* @param model the model to retrieve data types for
* @return the names of all data types defined within the specified model
*/
Collection<QName> getDataTypes(QName model);
/**
* @param name the name of the data type to retrieve
* @return the data type definition (or null, if it doesn't exist)
*/
DataTypeDefinition getDataType(QName name);
/**
* @param javaClass java class to find datatype for
* @return the data type definition (or null, if a mapping does not exist)
*/
DataTypeDefinition getDataType(Class javaClass);
/**
* @return the names of all types that have been registered with the Repository
*/
Collection<QName> getAllTypes();
/**
* @param model the model to retrieve types for
* @return the names of all types defined within the specified model
*/
Collection<QName> getTypes(QName model);
/**
* @param name the name of the type to retrieve
* @return the type definition (or null, if it doesn't exist)
*/
TypeDefinition getType(QName name);
/**
* Construct an anonymous type that combines the definitions of the specified
* type and aspects.
*
* @param type the type to start with
* @param aspects the aspects to combine with the type
* @return the anonymous type definition
*/
TypeDefinition getAnonymousType(QName type, Collection<QName> aspects);
/**
* @return the names of all aspects that have been registered with the Repository
*/
Collection<QName> getAllAspects();
/**
* @param model the model to retrieve aspects for
* @return the names of all aspects defined within the specified model
*/
Collection<QName> getAspects(QName model);
/**
* @param name the name of the aspect to retrieve
* @return the aspect definition (or null, if it doesn't exist)
*/
AspectDefinition getAspect(QName name);
/**
* @param name the name of the class (type or aspect) to retrieve
* @return the class definition (or null, if it doesn't exist)
*/
ClassDefinition getClass(QName name);
/**
* Determines whether a class is a sub-class of another class
*
* @param className the sub-class to test
* @param ofClassName the class to test against
* @return true => the class is a sub-class (or itself)
*/
boolean isSubClass(QName className, QName ofClassName);
/**
* Gets the definition of the property as defined by the specified Class.
*
* Note: A sub-class may override the definition of a property that's
* defined in a super-class.
*
* @param className the class name
* @param propertyName the property name
* @return the property definition (or null, if it doesn't exist)
*/
PropertyDefinition getProperty(QName className, QName propertyName);
/**
* Gets the definition of the property as defined by its owning Class.
*
* @param propertyName the property name
* @return the property definition (or null, if it doesn't exist)
*/
PropertyDefinition getProperty(QName propertyName);
/**
* Gets the definition of the association as defined by its owning Class.
*
* @param associationName the property name
* @return the association definition (or null, if it doesn't exist)
*/
AssociationDefinition getAssociation(QName associationName);
// TODO: Behaviour definitions
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName;
/**
* Thrown when a reference to an <b>aspect</b> is incorrect.
*
* @author Derek Hulley
*/
public class InvalidAspectException extends InvalidClassException
{
private static final long serialVersionUID = 3257290240330051893L;
public InvalidAspectException(QName aspectName)
{
super(null, aspectName);
}
public InvalidAspectException(String msg, QName aspectName)
{
super(msg, aspectName);
}
/**
* @return Returns the offending aspect name
*/
public QName getAspectName()
{
return getClassName();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.namespace.QName;
/**
* Thrown when an operation cannot be performed because the dictionary class
* reference does not exist.
*
*/
public class InvalidClassException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = 3256722870754293558L;
private QName className;
public InvalidClassException(QName className)
{
this(null, className);
}
public InvalidClassException(String msg, QName className)
{
super(msg);
this.className = className;
}
/**
* @return Returns the offending class name
*/
public QName getClassName()
{
return className;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName;
/**
* Thrown when an operation cannot be performed because a type is not recognised
* by the data dictionary
*
* @author Derek Hulley
*/
public class InvalidTypeException extends InvalidClassException
{
private static final long serialVersionUID = 3256722870754293558L;
public InvalidTypeException(QName typeName)
{
super(null, typeName);
}
public InvalidTypeException(String msg, QName typeName)
{
super(msg, typeName);
}
/**
* @return Returns the offending type name
*/
public QName getTypeName()
{
return getClassName();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import java.util.Date;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of a Model.
*
* @author David Caruana
*/
public interface ModelDefinition
{
/**
* @return the model name
*/
public QName getName();
/**
* @return the model description
*/
public String getDescription();
/**
* @return the model author
*/
public String getAuthor();
/**
* @return the date when the model was published
*/
public Date getPublishedDate();
/**
* @return the model version
*/
public String getVersion();
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of a Property.
*
* @author David Caruana
*/
public interface PropertyDefinition
{
/**
* @return defining model
*/
public ModelDefinition getModel();
/**
* @return the qualified name of the property
*/
public QName getName();
/**
* @return the human-readable class title
*/
public String getTitle();
/**
* @return the human-readable class description
*/
public String getDescription();
/**
* @return the default value
*/
public String getDefaultValue();
/**
* @return the qualified name of the property type
*/
public DataTypeDefinition getDataType();
/**
* @return Returns the owning class's defintion
*/
public ClassDefinition getContainerClass();
/**
* @return true => multi-valued, false => single-valued
*/
public boolean isMultiValued();
/**
* @return true => mandatory, false => optional
*/
public boolean isMandatory();
/**
* @return true => system maintained, false => client may maintain
*/
public boolean isProtected();
/**
* @return true => indexed, false => not indexed
*/
public boolean isIndexed();
/**
* @return true => stored in index
*/
public boolean isStoredInIndex();
/**
* @return true => tokenised when it is indexed (the stored value will not be tokenised)
*/
public boolean isTokenisedInIndex();
/**
* All non atomic properties will be indexed at the same time.
*
* @return true => The attribute must be indexed in the commit of the transaction.
* false => the indexing will be done in the background and may be out of date.
*/
public boolean isIndexedAtomically();
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.dictionary;
/**
* Read-only definition of a Type
*
* @author David Caruana
*/
public interface TypeDefinition extends ClassDefinition
{
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Interface for public and internal lock operations.
*
* @author Roy Wetherall
*/
public interface LockService
{
/**
* Places a lock on a node.
* <p>
* The lock prevents any other user or process from comitting updates
* to the node untill the lock is released.
* <p>
* The user reference passed indicates who the owner of the lock is.
* <p>
* A lock made with this call will never expire.
*
* @param nodeRef a reference to a node
* @param userName a reference to the user that will own the lock
* @param lockType the lock type
* @throws UnableToAquireLockException
* thrown if the lock could not be obtained
*/
public void lock(NodeRef nodeRef, LockType lockType)
throws UnableToAquireLockException;
/**
* Places a lock on a node.
* <p>
* The lock prevents any other user or process from comitting updates
* to the node untill the lock is released.
* <p>
* The user reference passed indicates who the owner of the lock is.
* <p>
* If the time to expire is 0 then the lock will never expire. Otherwise the
* timeToExpire indicates the number of seconds before the lock expires. When
* a lock expires the lock is considered to have been released.
* <p>
* If the node is already locked and the user is the lock owner then the lock will
* be renewed with the passed timeToExpire.
*
* @param nodeRef a reference to a node
* @param userName a reference to the user that will own the lock
* @param lockType the lock type
* @param timeToExpire the number of seconds before the locks expires.
* @throws UnableToAquireLockException
* thrown if the lock could not be obtained
*/
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire)
throws UnableToAquireLockException;
/**
* Places a lock on a node and optionally on all its children.
* <p>
* The lock prevents any other user or process from comitting updates
* to the node untill the lock is released.
* <p>
* The user reference passed indicates who the owner of the lock(s) is.
* If any one of the child locks can not be taken then an exception will
* be raised and all locks canceled.
* <p>
* If the time to expire is 0 then the lock will never expire. Otherwise the
* timeToExpire indicates the number of seconds before the lock expires. When
* a lock expires the lock is considered to have been released.
* <p>
* If the node is already locked and the user is the lock owner then the lock will
* be renewed with the passed timeToExpire.
*
* @param nodeRef a reference to a node
* @param userName a reference to the user that will own the lock(s)
* @param lockType the lock type
* @param timeToExpire the number of seconds before the locks expires.
* @param lockChildren if true indicates that all the children (and
* grandchildren, etc) of the node will also be locked,
* false otherwise
*
* @throws UnableToAquireLockException
* thrown if the lock could not be obtained
*/
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, boolean lockChildren)
throws UnableToAquireLockException;
/**
* Places a lock on all the nodes referenced in the passed list.
* <p>
* The lock prevents any other user or process from comitting updates
* to the node untill the lock is released.
* <p>
* The user reference passed indicates who the owner of the lock(s) is.
* If any one of the child locks can not be taken then an exception will
* be raised and all locks canceled.
* <p>
* If the time to expire is 0 then the lock will never expire. Otherwise the
* timeToExpire indicates the number of seconds before the lock expires. When
* a lock expires the lock is considered to have been released.
* <p>
* If the node is already locked and the user is the lock owner then the lock will
* be renewed with the passed timeToExpire.
*
* @param nodeRefs a list of node references
* @param userName a reference to the user that will own the lock(s)
* @param lockType the type of lock being created
* @param timeToExpire the number of seconds before the locks expires.
* @throws UnableToAquireLockException
* thrown if the lock could not be obtained
*/
public void lock(Collection<NodeRef> nodeRefs, LockType lockType, int timeToExpire)
throws UnableToAquireLockException;
/**
* Removes the lock on a node.
* <p>
* The user must have sufficient permissions to remove the lock (ie: be the
* owner of the lock or have admin rights) otherwise an exception will be raised.
*
* @param nodeRef a reference to a node
* @param userName the user reference
* @throws UnableToReleaseLockException
* thrown if the lock could not be released
*/
public void unlock(NodeRef nodeRef)
throws UnableToReleaseLockException;
/**
* Removes the lock on a node and optional on its children.
* <p>
* The user must have sufficient permissions to remove the lock(s) (ie: be
* the owner of the lock(s) or have admin rights) otherwise an exception
* will be raised.
* <p>
* If one of the child nodes is not locked then it will be ignored and
* the process continue without error.
* <p>
* If the lock on any one of the child nodes cannot be released then an
* exception will be raised.
*
* @param nodeRef a node reference
* @param userName the user reference
* @param lockChildren if true then all the children (and grandchildren, etc)
* of the node will also be unlocked, false otherwise
* @throws UnableToReleaseLockException
* thrown if the lock could not be released
*/
public void unlock(NodeRef nodeRef, boolean lockChildren)
throws UnableToReleaseLockException;
/**
* Removes a lock on the nodes provided.
* <p>
* The user must have sufficient permissions to remove the locks (ie: be
* the owner of the locks or have admin rights) otherwise an exception
* will be raised.
* <p>
* If one of the nodes is not locked then it will be ignored and the
* process will continue without an error.
* <p>
* If the lock on any one of the nodes cannot be released than an exception
* will be raised and the process rolled back.
*
* @param nodeRefs the node references
* @param userName the user reference
* @throws UnableToReleaseLockException
* thrown if the lock could not be released
*/
public void unlock(Collection<NodeRef> nodeRefs)
throws UnableToReleaseLockException;
/**
* Gets the lock status for the node reference relative to the current user.
*
* @see LockService#getLockStatus(NodeRef, NodeRef)
*
* @param nodeRef the node reference
* @return the lock status
*/
public LockStatus getLockStatus(NodeRef nodeRef);
/**
* Gets the lock type for the node indicated.
* <p>
* Returns null if the node is not locked.
* <p>
* Throws an exception if the node does not have the lock aspect.
*
* @param nodeRef the node reference
* @return the lock type, null is returned if the object in question has no
* lock
*/
public LockType getLockType(NodeRef nodeRef);
/**
* Checks to see if the node is locked or not. Gets the user reference from the current
* session.
* <p>
* Throws a NodeLockedException based on the lock status of the lock, the user ref and the
* lock type.
*
* @param nodeRef the node reference
*/
public void checkForLock(NodeRef nodeRef);
/**
* Get all the node references that the current user has locked.
*
* @param storeRef the store reference
* @return a list of nodes that the current user has locked.
*/
public List<NodeRef> getLocks(StoreRef storeRef);
/**
* Get all the node references that the current user has locked filtered by the provided lock type.
*
* @param storeRef the store reference
* @param lockType the lock type to filter the results by
*
* @return a list of nodes that the current user has locked filtered by the lock type provided
*/
public List<NodeRef> getLocks(StoreRef storeRef, LockType lockType);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
/**
* Enum used to indicate lock status.
*
* @author Roy Wetherall
*/
public enum LockStatus
{
NO_LOCK, // Indicates that there is no lock present
LOCKED, // Indicates that the node is locked
LOCK_OWNER, // Indicates that the node is locked and you have lock ownership rights
LOCK_EXPIRED // Indicates that the lock has expired and the node can be considered to be unlocked
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
/**
* Enum used to indicate lock type
*
* @author Roy Wetherall
*/
public enum LockType {READ_ONLY_LOCK, WRITE_LOCK}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
import java.text.MessageFormat;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Node locked exception class
*
* @author Roy Wetherall
*/
public class NodeLockedException extends AlfrescoRuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3762254149525582646L;
/**
* Error message
*/
private static final String ERROR_MESSAGE = "Can not perform operation since " +
"the node (id:{0}) is locked by another user.";
private static final String ERROR_MESSAGE_2 = "Can not perform operation {0} since " +
"the node (id:{1}) is locked by another user.";
/**
* @param message
*/
public NodeLockedException(NodeRef nodeRef)
{
super(MessageFormat.format(ERROR_MESSAGE, new Object[]{nodeRef.getId()}));
}
public NodeLockedException(NodeRef nodeRef, String operation)
{
super(MessageFormat.format(ERROR_MESSAGE_2, new Object[]{operation, nodeRef.getId()}));
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
import java.text.MessageFormat;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* @author Roy Wetherall
*/
public class UnableToAquireLockException extends RuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3258689892710889781L;
/**
* Error message
*/
private final static String ERROR_MESSAGE = "The node (id: {0})could not be locked since it" +
" is already locked by antoher user.";
/**
* Constructor
*/
public UnableToAquireLockException(NodeRef nodeRef)
{
super(MessageFormat.format(ERROR_MESSAGE, new Object[]{nodeRef.getId()}));
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.lock;
import java.text.MessageFormat;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Runtime exception class
*
* @author Roy Wetherall
*/
public class UnableToReleaseLockException extends RuntimeException
{
/**
* Serial verison UID
*/
private static final long serialVersionUID = 3257565088071432243L;
/**
* Error message
*/
private static final String ERROR_MESSAGE =
"You have insufficent priveleges to realese the " +
"lock on the node (id: {0}). The node is locked by " +
"another user.";
/**
* Constructor
*/
public UnableToReleaseLockException(NodeRef nodeRef)
{
super(MessageFormat.format(ERROR_MESSAGE, new Object[]{nodeRef.getId()}));
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.model;
/**
* Common, checked exception thrown when an operation fails because
* of a name clash.
*
* @author Derek Hulley
*/
public class FileExistsException extends Exception
{
private static final long serialVersionUID = -4133713912784624118L;
private FileInfo existing;
public FileExistsException(FileInfo existing)
{
super("" +
(existing.isFolder() ? "Folder " : "File ") +
existing.getName() +
" already exists");
this.existing = existing;
}
public FileInfo getExisting()
{
return existing;
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.model;
import java.util.List;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Provides methods specific to manipulating {@link org.alfresco.model.ContentModel#TYPE_CONTENT files}
* and {@link org.alfresco.model.ContentModel#TYPE_FOLDER folders}.
*
* @see org.alfresco.model.ContentModel
*
* @author Derek Hulley
*/
public interface FileFolderService
{
/**
* Lists immediate child files and folders of the given context node
*
* @param contextNodeRef the node to start searching in
* @return Returns a list of matching files and folders
*/
public List<FileInfo> list(NodeRef contextNodeRef);
/**
* Lists all immediate child files of the given context node
*
* @param folderNodeRef the folder to start searching in
* @return Returns a list of matching files
*/
public List<FileInfo> listFiles(NodeRef folderNodeRef);
/**
* Lists all immediate child folders of the given context node
*
* @param contextNodeRef the node to start searching in
* @return Returns a list of matching folders
*/
public List<FileInfo> listFolders(NodeRef contextNodeRef);
/**
* Searches for all files and folders with the matching name pattern,
* using wildcard characters <b>*</b> and <b>?</b>.
*
* @see #search(NodeRef, String, boolean, boolean, boolean)
*/
public List<FileInfo> search(
NodeRef contextNodeRef,
String namePattern,
boolean includeSubFolders);
/**
* Perform a search against the name of the files or folders within a hierarchy.
* Wildcard characters are <b>*</b> and <b>?</b>.
*
* @param contextNodeRef the context of the search. This node will never be returned
* as part of the search results.
* @param namePattern the name of the file or folder to search for, or a
* {@link org.alfresco.util.SearchLanguageConversion#DEF_LUCENE wildcard} pattern
* to search for.
* @param fileSearch true if file types are to be included in the search results
* @param folderSearch true if folder types are to be included in the search results
* @param includeSubFolders true to search the entire hierarchy below the search context
* @return Returns a list of file or folder matches
*/
public List<FileInfo> search(
NodeRef contextNodeRef,
String namePattern,
boolean fileSearch,
boolean folderSearch,
boolean includeSubFolders);
/**
* Rename a file or folder in its current location
*
* @param fileFolderRef the file or folder to rename
* @param newName the new name
* @return Return the new file info
* @throws FileExistsException if a file or folder with the new name already exists
* @throws FileNotFoundException the file or folder reference doesn't exist
*/
public FileInfo rename(NodeRef fileFolderRef, String newName) throws FileExistsException, FileNotFoundException;
/**
* Move a file or folder to a new name and/or location.
* <p>
* If both the parent folder and name remain the same, then nothing is done.
*
* @param sourceNodeRef the file or folder to move
* @param targetParentRef the new parent node to move the node to - null means rename in situ
* @param newName the name to change the file or folder to - null to keep the existing name
* @return Returns the new file info
* @throws FileExistsException
* @throws FileNotFoundException
*/
public FileInfo move(NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
throws FileExistsException, FileNotFoundException;
/**
* Copy a source file or folder. The source can be optionally renamed and optionally
* moved into another folder.
* <p>
* If both the parent folder and name remain the same, then nothing is done.
*
* @param sourceNodeRef the file or folder to copy
* @param targetParentRef the new parent node to copy the node to - null means rename in situ
* @param newName the new name, or null to keep the existing name.
* @return Return the new file info
* @throws FileExistsException
* @throws FileNotFoundException
*/
public FileInfo copy(NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
throws FileExistsException, FileNotFoundException;
/**
* Create a file or folder; or any valid node of type derived from file or folder
*
* @param parentNodeRef the parent node. The parent must be a valid
* {@link org.alfresco.model.ContentModel#TYPE_CONTAINER container}.
* @param name the name of the node
* @param typeQName the type to create
* @return Returns the new node's file information
* @throws FileExistsException
*/
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException;
/**
* Delete a file or folder
*
* @param nodeRef the node to delete
*/
public void delete(NodeRef nodeRef);
/**
* Checks for the presence of, and creates as necessary, the folder structure in the provided path.
* <p>
* An empty path list is not allowed as it would be impossible to necessarily return file info
* for the parent node - it might not be a folder node.
*
* @param parentNodeRef the node under which the path will be created
* @param pathElements the folder name path to create - may not be empty
* @param folderTypeQName the types of nodes to create. This must be a valid subtype of
* {@link org.alfresco.model.ContentModel#TYPE_FOLDER they folder type}.
* @return Returns the info of the last folder in the path.
*/
public FileInfo makeFolders(NodeRef parentNodeRef, List<String> pathElements, QName folderTypeQName);
/**
* Get the file or folder names from the root down to and including the node provided.
* <ul>
* <li>The root node can be of any type and is not included in the path list.</li>
* <li>Only the primary path is considered. If the target node is not a descendent of the
* root along purely primary associations, then an exception is generated.</li>
* <li>If an invalid type is encoutered along the path, then an exception is generated.</li>
* </ul>
*
* @param rootNodeRef the start of the returned path, or null if the <b>store</b> root
* node must be assumed.
* @param nodeRef a reference to the file or folder
* @return Returns a list of file/folder infos from the root (excluded) down to and
* including the destination file or folder
* @throws FileNotFoundException if the node could not be found
*/
public List<FileInfo> getNamePath(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException;
/**
* Resolve a file or folder name path from a given root node down to the final node.
*
* @param rootNodeRef the start of the path given, i.e. the '/' in '/A/B/C' for example
* @param pathElements a list of names in the path
* @return Returns the info of the file or folder
* @throws FileNotFoundException if no file or folder exists along the path
*/
public FileInfo resolveNamePath(NodeRef rootNodeRef, List<String> pathElements) throws FileNotFoundException;
/**
* Get the file info (name, folder, etc) for the given node
*
* @param nodeRef the node to get info for
* @return Returns the file info or null if the node does not represent a file or folder
*/
public FileInfo getFileInfo(NodeRef nodeRef);
public ContentReader getReader(NodeRef nodeRef);
public ContentWriter getWriter(NodeRef nodeRef);
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.model;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Common file information. The implementations may store the properties for the lifetime
* of this instance; i.e. the values are transient and can be used as read-only values for
* a short time only.
*
* @author Derek Hulley
*/
public interface FileInfo
{
/**
* @return Returns a reference to the low-level node representing this file
*/
public NodeRef getNodeRef();
/**
* @return Return true if this instance represents a folder, false if this represents a file
*/
public boolean isFolder();
/**
* @return Returns the name of the file or folder within the parent folder
*/
public String getName();
/**
* @return Returns the date the node was created
*/
public Date getCreatedDate();
/**
* @return Returns the modified date
*/
public Date getModifiedDate();
/**
* Get the content data. This is only valid for {@link #isFolder() files}.
*
* @return Returns the content data
*/
public ContentData getContentData();
/**
* @return Returns all the node properties
*/
public Map<QName, Serializable> getProperties();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.model;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Common, checked exception thrown when a file or folder could not be found
*
* @author Derek Hulley
*/
public class FileNotFoundException extends Exception
{
private static final long serialVersionUID = 2558540174977806285L;
public FileNotFoundException(NodeRef nodeRef)
{
super("No file or folder found for node reference: " + nodeRef);
}
public FileNotFoundException(String msg)
{
super(msg);
}
}

View File

@@ -0,0 +1,11 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
Model-specific services.
<p/>
These services give <b>much</b> simpler APIs for manipulating nodes structures
conforming to specific models within the data dictionary.
</body>
</html>

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Store-related exception that keeps a handle to the store reference
*
* @author Derek Hulley
*/
public abstract class AbstractStoreException extends RuntimeException
{
private StoreRef storeRef;
public AbstractStoreException(StoreRef storeRef)
{
this(null, storeRef);
}
public AbstractStoreException(String msg, StoreRef storeRef)
{
super(msg);
this.storeRef = storeRef;
}
/**
* @return Returns the offending store reference
*/
public StoreRef getStoreRef()
{
return storeRef;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.text.MessageFormat;
import org.alfresco.service.namespace.QName;
/**
* Used to indicate that an aspect is missing from a node.
*
* @author Roy Wetherall
*/
public class AspectMissingException extends RuntimeException
{
private static final long serialVersionUID = 3257852099244210228L;
private QName missingAspect;
private NodeRef nodeRef;
/**
* Error message
*/
private static final String ERROR_MESSAGE = "The {0} aspect is missing from this node (id: {1}). " +
"It is required for this operation.";
/**
* Constructor
*/
public AspectMissingException(QName missingAspect, NodeRef nodeRef)
{
super(MessageFormat.format(ERROR_MESSAGE, new Object[]{missingAspect.toString(), nodeRef.getId()}));
this.missingAspect = missingAspect;
this.nodeRef = nodeRef;
}
public QName getMissingAspect()
{
return missingAspect;
}
public NodeRef getNodeRef()
{
return nodeRef;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.service.namespace.QName;
/**
* Thrown when an operation could not be performed because a named association already
* exists between two nodes
*
* @author Derek Hulley
*/
public class AssociationExistsException extends RuntimeException
{
private static final long serialVersionUID = 3256440317824874800L;
private NodeRef sourceRef;
private NodeRef targetRef;
private QName qname;
/**
* @param sourceRef the source of the association
* @param targetRef the target of the association
* @param qname the qualified name of the association
*/
public AssociationExistsException(NodeRef sourceRef, NodeRef targetRef, QName qname)
{
super();
this.sourceRef = sourceRef;
this.targetRef = targetRef;
this.qname = qname;
}
public NodeRef getSourceRef()
{
return sourceRef;
}
public NodeRef getTargetRef()
{
return targetRef;
}
public QName getQName()
{
return qname;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* This class represents a regular, named node relationship between two nodes.
*
* @author Derek Hulley
*/
public class AssociationRef implements EntityRef, Serializable
{
private static final long serialVersionUID = 3977867284482439475L;
private NodeRef sourceRef;
private QName assocTypeQName;
private NodeRef targetRef;
/**
* Construct a representation of a source --- name ----> target
* relationship.
*
* @param sourceRef
* the source reference - never null
* @param assocTypeQName
* the qualified name of the association type - never null
* @param targetRef
* the target node reference - never null.
*/
public AssociationRef(NodeRef sourceRef, QName assocTypeQName, NodeRef targetRef)
{
this.sourceRef = sourceRef;
this.assocTypeQName = assocTypeQName;
this.targetRef = targetRef;
// check
if (sourceRef == null)
{
throw new IllegalArgumentException("Source reference may not be null");
}
if (assocTypeQName == null)
{
throw new IllegalArgumentException("QName may not be null");
}
if (targetRef == null)
{
throw new IllegalArgumentException("Target reference may not be null");
}
}
/**
* Get the qualified name of the source-target association
*
* @return Returns the qualified name of the source-target association.
*/
public QName getTypeQName()
{
return assocTypeQName;
}
/**
* @return Returns the child node reference - never null
*/
public NodeRef getTargetRef()
{
return targetRef;
}
/**
* @return Returns the parent node reference, which may be null if this
* represents the imaginary reference to the root node
*/
public NodeRef getSourceRef()
{
return sourceRef;
}
/**
* Compares:
* <ul>
* <li>{@link #sourceRef}</li>
* <li>{@link #targetRef}</li>
* <li>{@link #assocTypeQName}</li>
* </ul>
*/
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof ChildAssociationRef))
{
return false;
}
AssociationRef other = (AssociationRef) o;
return (EqualsHelper.nullSafeEquals(this.sourceRef, other.sourceRef)
&& EqualsHelper.nullSafeEquals(this.assocTypeQName, other.assocTypeQName)
&& EqualsHelper.nullSafeEquals(this.targetRef, other.targetRef));
}
public int hashCode()
{
int hashCode = (getSourceRef() == null) ? 0 : getSourceRef().hashCode();
hashCode = 37 * hashCode + ((getTypeQName() == null) ? 0 : getTypeQName().hashCode());
hashCode = 37 * hashCode + getTargetRef().hashCode();
return hashCode;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append(getSourceRef());
buffer.append(" --- ").append(getTypeQName()).append(" ---> ");
buffer.append(getTargetRef());
return buffer.toString();
}
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* This class represents a child relationship between two nodes. This
* relationship is named.
* <p>
* So it requires the parent node ref, the child node ref and the name of the
* child within the particular parent.
* <p>
* This combination is not a unique identifier for the relationship with regard
* to structure. In use this does not matter as we have no concept of order,
* particularly in the index.
*
* @author andyh
*
*/
public class ChildAssociationRef
implements EntityRef, Comparable<ChildAssociationRef>, Serializable
{
private static final long serialVersionUID = 4051322336257127729L;
private QName assocTypeQName;
private NodeRef parentRef;
private QName childQName;
private NodeRef childRef;
private boolean isPrimary;
private int nthSibling;
/**
* Construct a representation of a parent --- name ----> child relationship.
*
* @param assocTypeQName
* the type of the association
* @param parentRef
* the parent reference - may be null
* @param childQName
* the qualified name of the association - may be null
* @param childRef
* the child node reference. This must not be null.
* @param isPrimary
* true if this represents the primary parent-child relationship
* @param nthSibling
* the nth association with the same properties. Usually -1 to be
* ignored.
*/
public ChildAssociationRef(
QName assocTypeQName,
NodeRef parentRef,
QName childQName,
NodeRef childRef,
boolean isPrimary,
int nthSibling)
{
this.assocTypeQName = assocTypeQName;
this.parentRef = parentRef;
this.childQName = childQName;
this.childRef = childRef;
this.isPrimary = isPrimary;
this.nthSibling = nthSibling;
// check
if (childRef == null)
{
throw new IllegalArgumentException("Child reference may not be null");
}
}
/**
* Constructs a <b>non-primary</b>, -1th sibling parent-child association
* reference.
*
* @see ChildAssociationRef#ChildAssocRef(QName, NodeRef, QName, NodeRef, boolean, int)
*/
public ChildAssociationRef(QName assocTypeQName, NodeRef parentRef, QName childQName, NodeRef childRef)
{
this(assocTypeQName, parentRef, childQName, childRef, false, -1);
}
/**
* Compares:
* <ul>
* <li>{@link #assocTypeQName}</li>
* <li>{@link #parentRef}</li>
* <li>{@link #childRef}</li>
* <li>{@link #childQName}</li>
* </ul>
*/
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof ChildAssociationRef))
{
return false;
}
ChildAssociationRef other = (ChildAssociationRef) o;
return (EqualsHelper.nullSafeEquals(this.assocTypeQName, other.assocTypeQName)
&& EqualsHelper.nullSafeEquals(this.parentRef, other.parentRef)
&& EqualsHelper.nullSafeEquals(this.childQName, other.childQName)
&& EqualsHelper.nullSafeEquals(this.childRef, other.childRef));
}
public int hashCode()
{
int hashCode = ((getTypeQName() == null) ? 0 : getTypeQName().hashCode());
hashCode = 37 * hashCode + ((getParentRef() == null) ? 0 : getParentRef().hashCode());
hashCode = 37 * hashCode + ((getQName() == null) ? 0 : getQName().hashCode());
hashCode = 37 * hashCode + getChildRef().hashCode();
return hashCode;
}
/**
* @see #setNthSibling(int)
*/
public int compareTo(ChildAssociationRef another)
{
int thisVal = this.nthSibling;
int anotherVal = another.nthSibling;
return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("[").append(getTypeQName()).append("]");
sb.append(getParentRef());
sb.append(" --- ").append(getQName()).append(" ---> ");
sb.append(getChildRef());
return sb.toString();
}
/**
* Get the qualified name of the association type
*
* @return Returns the qualified name of the parent-child association type
* as defined in the data dictionary. It may be null if this is the
* imaginary association to the root node.
*/
public QName getTypeQName()
{
return assocTypeQName;
}
/**
* Get the qualified name of the parent-child association
*
* @return Returns the qualified name of the parent-child association. It
* may be null if this is the imaginary association to a root node.
*/
public QName getQName()
{
return childQName;
}
/**
* @return Returns the child node reference - never null
*/
public NodeRef getChildRef()
{
return childRef;
}
/**
* @return Returns the parent node reference, which may be null if this
* represents the imaginary reference to the root node
*/
public NodeRef getParentRef()
{
return parentRef;
}
/**
* @return Returns true if this represents a primary association
*/
public boolean isPrimary()
{
return isPrimary;
}
/**
* @return Returns the nth sibling required
*/
public int getNthSibling()
{
return nthSibling;
}
/**
* Allows post-creation setting of the ordering index. This is a helper
* so that sorted sets and lists can be easily sorted.
* <p>
* This index is <b>in no way absolute</b> and should change depending on
* the results that appear around this instance. Therefore, the sibling
* number cannot be used to construct, say, sibling number 5. Sibling
* number 5 will exist only in results where there are siblings 1 - 4.
*
* @param nthSibling the sibling index
*/
public void setNthSibling(int nthSibling)
{
this.nthSibling = nthSibling;
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.service.transaction.TransactionService;
/**
* Interface for instances that provide read and write access to content.
*
* @author Derek Hulley
*/
public interface ContentAccessor
{
/**
* Use this method to register any interest in events against underlying
* content streams.
* {@link #getContentOutputStream() output stream}.
* <p>
* This method can only be used before the content stream has been retrieved.
* <p>
* When the stream has been closed, all listeners will be called
* within a {@link #setTransactionService(TransactionService) transaction} -
* to this end, a {@link TransactionService} must have been set as well.
*
* @param listener a listener that will be called for output stream
* event notification
*
* @see #setTransactionService(TransactionService)
*/
public void addListener(ContentStreamListener listener);
/**
* Set the transaction provider that will be used when stream listeners are called.
*
* @param transactionService a transaction provider
*/
public void setTransactionService(TransactionService transactionService);
/**
* Gets the size of the content that this reader references.
*
* @return Returns the document byte length, or <code>OL</code> if the
* content doesn't {@link #exists() exist}.
*/
public long getSize();
/**
* Get the data representation of the content being accessed.
* <p>
* The content {@link #setMimetype(String) mimetype } must be set before this
* method is called as the content data requires a mimetype whenever the
* content URL is specified.
*
* @return Returns the content data
*
* @see ContentData#ContentData(String, String, long, String)
*/
public ContentData getContentData();
/**
* Retrieve the URL that this accessor references
*
* @return the content URL
*/
public String getContentUrl();
/**
* Get the content mimetype
*
* @return Returns a content mimetype
*/
public String getMimetype();
/**
* Set the mimetype that must be used for accessing the content
*
* @param mimetype the content mimetype
*/
public void setMimetype(String mimetype);
/**
* Get the encoding of the content being accessed
*
* @return Returns a valid java String encoding
*/
public String getEncoding();
/**
* Set the <code>String</code> encoding for this accessor
*
* @param encoding a java-recognised encoding format
*/
public void setEncoding(String encoding);
}

View File

@@ -0,0 +1,246 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.util.EqualsHelper;
/**
* The compound property representing content
*
* @author Derek Hulley
*/
public class ContentData implements Serializable
{
private static final long serialVersionUID = 8979634213050121462L;
private static char[] INVALID_CONTENT_URL_CHARS = new char[] {'|'};
private final String contentUrl;
private final String mimetype;
private final long size;
private final String encoding;
/**
* Construct a content property from a string
*
* @param contentPropertyStr the string representing the content details
* @return Returns a bean version of the string
*/
public static ContentData createContentProperty(String contentPropertyStr)
{
// get the content url
int contentUrlIndex = contentPropertyStr.indexOf("contentUrl=");
if (contentUrlIndex == -1)
{
throw new AlfrescoRuntimeException(
"ContentData string does not have a content URL: " +
contentPropertyStr);
}
int mimetypeIndex = contentPropertyStr.indexOf("|mimetype=", contentUrlIndex + 11);
if (mimetypeIndex == -1)
{
throw new AlfrescoRuntimeException(
"ContentData string does not have a mimetype: " +
contentPropertyStr);
}
int sizeIndex = contentPropertyStr.indexOf("|size=", mimetypeIndex + 10);
if (sizeIndex == -1)
{
throw new AlfrescoRuntimeException(
"ContentData string does not have a size: " +
contentPropertyStr);
}
int encodingIndex = contentPropertyStr.indexOf("|encoding=", sizeIndex + 6);
if (encodingIndex == -1)
{
throw new AlfrescoRuntimeException(
"ContentData string does not have an encoding: " +
contentPropertyStr);
}
String contentUrl = contentPropertyStr.substring(contentUrlIndex + 11, mimetypeIndex);
if (contentUrl.length() == 0)
contentUrl = null;
String mimetype = contentPropertyStr.substring(mimetypeIndex + 10, sizeIndex);
if (mimetype.length() == 0)
mimetype = null;
String sizeStr = contentPropertyStr.substring(sizeIndex + 6, encodingIndex);
if (sizeStr.length() == 0)
sizeStr = "0";
String encoding = contentPropertyStr.substring(encodingIndex + 10);
if (encoding.length() == 0)
encoding = null;
long size = Long.valueOf(sizeStr);
ContentData property = new ContentData(contentUrl, mimetype, size, encoding);
// done
return property;
}
/**
* Constructs a new instance using the existing one as a template, but replacing the
* mimetype
*
* @param existing an existing set of content data, null to use default values
* @param mimetype the mimetype to set
* @return Returns a new, immutable instance of the data
*/
public static ContentData setMimetype(ContentData existing, String mimetype)
{
ContentData ret = new ContentData(
existing == null ? null : existing.contentUrl,
mimetype,
existing == null ? 0L : existing.size,
existing == null ? "UTF-8" : existing.encoding);
// done
return ret;
}
/**
* Create a compound set of data representing a single instance of <i>content</i>.
* <p>
* In order to ensure data integrity, the {@link #getMimetype() mimetype}
* must be set if the {@link #getContentUrl() content URL} is set.
*
* @param contentUrl the content URL. If this value is non-null, then the
* <b>mimetype</b> must be supplied.
* @param mimetype the content mimetype. This is mandatory if the <b>contentUrl</b> is specified.
* @param size the content size.
* @param encoding the content encoding.
*/
public ContentData(String contentUrl, String mimetype, long size, String encoding)
{
checkContentUrl(contentUrl, mimetype);
this.contentUrl = contentUrl;
this.mimetype = mimetype;
this.size = size;
this.encoding = encoding;
}
public boolean equals(Object obj)
{
if (obj == this)
return true;
else if (obj == null)
return false;
else if (!(obj instanceof ContentData))
return false;
ContentData that = (ContentData) obj;
return (EqualsHelper.nullSafeEquals(this.contentUrl, that.contentUrl) &&
EqualsHelper.nullSafeEquals(this.mimetype, that.mimetype) &&
this.size == that.size &&
EqualsHelper.nullSafeEquals(this.encoding, that.encoding));
}
/**
* @return Returns a string of form: <code>contentUrl=xxx;mimetype=xxx;size=xxx;encoding=xxx</code>
*/
public String toString()
{
StringBuilder sb = new StringBuilder(80);
sb.append("contentUrl=").append(contentUrl == null ? "" : contentUrl)
.append("|mimetype=").append(mimetype == null ? "" : mimetype)
.append("|size=").append(size)
.append("|encoding=").append(encoding == null ? "" : encoding);
return sb.toString();
}
/**
* @return Returns a URL identifying the specific location of the content.
* The URL must identify, within the context of the originating content
* store, the exact location of the content.
* @throws ContentIOException
*/
public String getContentUrl()
{
return contentUrl;
}
/**
* Checks that the content URL is correct, and also that the mimetype is
* non-null if the URL is present.
*
* @param contentUrl the content URL to check
* @param mimetype
*/
private void checkContentUrl(String contentUrl, String mimetype)
{
// check the URL
if (contentUrl != null && contentUrl.length() > 0)
{
for (int i = 0; i < INVALID_CONTENT_URL_CHARS.length; i++)
{
for (int j = contentUrl.length() - 1; j > -1; j--)
{
if (contentUrl.charAt(j) == INVALID_CONTENT_URL_CHARS[i])
{
throw new IllegalArgumentException(
"The content URL contains an invalid char: \n" +
" content URL: " + contentUrl + "\n" +
" char: " + INVALID_CONTENT_URL_CHARS[i] + "\n" +
" position: " + j);
}
}
}
// check that mimetype is present if URL is present
if (mimetype == null)
{
throw new IllegalArgumentException(
"The content mimetype must be set whenever the URL is set: \n" +
" content URL: " + contentUrl + "\n" +
" mimetype: " + mimetype);
}
}
}
/**
* Gets content's mimetype.
*
* @return Returns a standard mimetype for the content or null if the mimetype
* is unkown
*/
public String getMimetype()
{
return mimetype;
}
/**
* Get the content's size
*
* @return Returns the size of the content
*/
public long getSize()
{
return size;
}
/**
* Gets the content's encoding.
*
* @return Returns a valid Java encoding, typically a character encoding, or
* null if the encoding is unkown
*/
public String getEncoding()
{
return encoding;
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import junit.framework.TestCase;
/**
* @see org.alfresco.service.cmr.repository.ContentData
*
* @author Derek Hulley
*/
public class ContentDataTest extends TestCase
{
public ContentDataTest(String name)
{
super(name);
}
public void testToAndFromString() throws Exception
{
ContentData property = new ContentData(null, null, 0L, null);
// check null string
String propertyStr = property.toString();
assertEquals("Null values not converted correctly",
"contentUrl=|mimetype=|size=0|encoding=", propertyStr);
// convert back
ContentData checkProperty = ContentData.createContentProperty(propertyStr);
assertEquals("Conversion from string failed", property, checkProperty);
property = new ContentData("uuu", "mmm", 123L, "eee");
// convert to a string
propertyStr = property.toString();
assertEquals("Incorrect property string representation",
"contentUrl=uuu|mimetype=mmm|size=123|encoding=eee", propertyStr);
// convert back
checkProperty = ContentData.createContentProperty(propertyStr);
assertEquals("Conversion from string failed", property, checkProperty);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Wraps a general <code>Exceptions</code> that occurred while reading or writing
* content.
*
* @see Throwable#getCause()
*
* @author Derek Hulley
*/
public class ContentIOException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = 3258130249983276087L;
public ContentIOException(String msg)
{
super(msg);
}
public ContentIOException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ReadableByteChannel;
/**
* Represents a handle to read specific content. Content may only be accessed
* once per instance.
* <p>
* Implementations of this interface <b>might</b> be <code>Serializable</code>
* but client code could should check suitability before attempting to serialize
* it.
* <p>
* Implementations that are able to provide inter-VM streaming, such as accessing
* WebDAV, would be <code>Serializable</code>. An accessor that has to access a
* local file on the server could not provide inter-VM streaming unless it specifically
* makes remote calls and opens sockets, etc.
*
* @see org.alfresco.service.cmr.repository.ContentWriter
*
* @author Derek Hulley
*/
public interface ContentReader extends ContentAccessor
{
/**
* Convenience method to get another reader onto the underlying content.
*
* @return Returns a reader onto the underlying content
* @throws ContentIOException
*/
public ContentReader getReader() throws ContentIOException;
/**
* Check if the {@link ContentAccessor#getContentUrl() underlying content} is present.
*
* @return Returns true if there is content at the URL refered to by this reader
*/
public boolean exists();
/**
* Gets the time of the last modification of the underlying content.
*
* @return Returns the last modification time using the standard <tt>long</tt>
* time, or <code>0L</code> if the content doesn't {@link #exists() exist}.
*
* @see System#currentTimeMillis()
*/
public long getLastModified();
/**
* Convenience method to find out if this reader has been closed.
* Once closed, the content can no longer be read. This method could
* be used to wait for a particular read operation to complete, for example.
*
* @return Return true if the content input stream has been used and closed
* otherwise false.
*/
public boolean isClosed();
/**
* Provides low-level access to the underlying content.
* <p>
* Once the stream is provided to a client it should remain active
* (subject to any timeouts) until closed by the client.
*
* @return Returns a stream that can be read at will, but must be closed when completed
* @throws ContentIOException
*/
public ReadableByteChannel getReadableChannel() throws ContentIOException;
/**
* Get a stream to read from the underlying channel
*
* @return Returns an input stream onto the underlying channel
* @throws ContentIOException
*
* @see #getReadableChannel()
*/
public InputStream getContentInputStream() throws ContentIOException;
/**
* Gets content from the repository.
* <p>
* All resources will be closed automatically.
* <p>
* Care must be taken that the bytes read from the stream are properly
* decoded according to the {@link ContentAccessor#getEncoding() encoding}
* property.
*
* @param os the stream to which to write the content
* @throws ContentIOException
*
* @see #getReadableChannel()
*/
public void getContent(OutputStream os) throws ContentIOException;
/**
* Gets content from the repository direct to file
* <p>
* All resources will be closed automatically.
*
* @param file the file to write the content to - it will be overwritten
* @throws ContentIOException
*
* @see #getContentInputStream()
*/
public void getContent(File file) throws ContentIOException;
/**
* Gets content from the repository direct to <code>String</code>.
* <p>
* If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used
* otherwise the default system <tt>byte[]</tt> to <tt>String</tt> conversion
* will be used.
* <p>
* All resources will be closed automatically.
* <p>
* <b>WARNING: </b> This should only be used when the size of the content
* is known in advance.
*
* @return Returns a String representation of the content
* @throws ContentIOException
*
* @see #getContentString(int)
* @see #getContentInputStream()
* @see String#String(byte[])
*/
public String getContentString() throws ContentIOException;
/**
* Gets content from the repository direct to <code>String</code>, but limiting
* the string size to a given number of characters.
* <p>
* If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used
* otherwise the default system <tt>byte[]</tt> to <tt>String</tt> conversion
* will be used.
* <p>
* All resources will be closed automatically.
*
* @param length the maximum number of characters to retrieve
* @return Returns a truncated String representation of the content
* @throws ContentIOException
* @throws java.lang.IllegalArgumentException if the length is < 0 or > {@link Integer#MAX_VALUE}
*
* @see #getContentString()
* @see #getContentInputStream()
* @see String#String(byte[])
*/
public String getContentString(int length) throws ContentIOException;
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.namespace.QName;
/**
* Provides methods for accessing and transforming content.
* <p>
* Implementations of this service are primarily responsible for ensuring
* that the correct store is used to access content, and that reads and
* writes for the same node reference are routed to the same store instance.
* <p>
* The mechanism for selecting an appropriate store is not prescribed by
* the interface, but typically the decision will be made on the grounds
* of content type.
* <p>
* Whereas the content stores have no knowledge of nodes other than their
* references, the <code>ContentService</code> <b>is</b> responsible for
* ensuring that all the relevant node-content relationships are maintained.
*
* @see org.alfresco.repo.content.ContentStore
* @see org.alfresco.service.cmr.repository.ContentReader
* @see org.alfresco.service.cmr.repository.ContentWriter
*
* @author Derek Hulley
*/
public interface ContentService
{
/**
* Gets a reader for the content associated with the given node property.
* <p>
* If a content URL is present for the given node then a reader <b>must</b>
* be returned. The {@link ContentReader#exists() exists} method should then
* be used to detect 'missing' content.
*
* @param nodeRef a reference to a node having a content property
* @param propertyQName the name of the property, which must be of type <b>content</b>
* @return Returns a reader for the content associated with the node property,
* or null if no content has been written for the property
* @throws InvalidNodeRefException if the node doesn't exist
* @throws InvalidTypeException if the node is not of type <b>content</b>
*
* @see org.alfresco.repo.content.filestore.FileContentReader#getSafeContentReader(ContentReader, String, Object[])
*/
public ContentReader getReader(NodeRef nodeRef, QName propertyQName)
throws InvalidNodeRefException, InvalidTypeException;
/**
* Get a content writer for the given node property, choosing to optionally have
* the node property updated automatically when the content stream closes.
* <p>
* If the update flag is off, then the state of the node property will remain unchanged
* regardless of the state of the written binary data. If the flag is on, then the node
* property will be updated on the same thread as the code that closed the write
* channel.
*
* @param nodeRef a reference to a node having a content property
* @param propertyQName the name of the property, which must be of type <b>content</b>
* @param update true if the property must be updated atomically when the content write
* stream is closed (attaches a listener to the stream); false if the client code
* will perform the updates itself.
* @return Returns a writer for the content associated with the node property
* @throws InvalidNodeRefException if the node doesn't exist
* @throws InvalidTypeException if the node property is not of type <b>content</b>
*/
public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update)
throws InvalidNodeRefException, InvalidTypeException;
/**
* Gets a writer to a temporary location. The longevity of the stored
* temporary content is determined by the system.
*
* @return Returns a writer onto a temporary location
*/
public ContentWriter getTempWriter();
/**
* Transforms the content from the reader and writes the content
* back out to the writer.
* <p>
* The mimetypes used for the transformation must be set both on
* the {@link ContentAccessor#getMimetype() reader} and on the
* {@link ContentAccessor#getMimetype() writer}.
*
* @param reader the source content location and mimetype
* @param writer the target content location and mimetype
* @throws NoTransformerException if no transformer exists for the
* given source and target mimetypes of the reader and writer
* @throws ContentIOException if the transformation fails
*/
public void transform(ContentReader reader, ContentWriter writer)
throws NoTransformerException, ContentIOException;
/**
* Returns whether a transformer exists that can read the content from
* the reader and write the content back out to the writer.
* <p>
* The mimetypes used for the transformation must be set both on
* the {@link ContentAccessor#getMimetype() reader} and on the
* {@link ContentAccessor#getMimetype() writer}.
*
* @param reader the source content location and mimetype
* @param writer the target content location and mimetype
*
* @return true if a transformer exists, false otherwise
*/
public boolean isTransformable(ContentReader reader, ContentWriter writer);
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Listens for notifications w.r.t. content. This includes receiving notifications
* of the opening and closing of the content streams.
*
* @author Derek Hulley
*/
public interface ContentStreamListener
{
/**
* Called when the stream associated with a reader or writer is closed
*
* @throws ContentIOException
*/
public void contentStreamClosed() throws ContentIOException;
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.WritableByteChannel;
/**
* Represents a handle to write specific content. Content may only be accessed
* once per instance.
* <p>
* Implementations of this interface <b>might</b> be <code>Serializable</code>
* but client code could should check suitability before attempting to serialize
* it.
* <p>
* Implementations that are able to provide inter-VM streaming, such as accessing
* WebDAV, would be <code>Serializable</code>. An accessor that has to access a
* local file on the server could not provide inter-VM streaming unless it specifically
* makes remote calls and opens sockets, etc.
*
* @see org.alfresco.service.cmr.repository.ContentReader
*
* @author Derek Hulley
*/
public interface ContentWriter extends ContentAccessor
{
/**
* Convenience method to get a reader onto newly written content. This
* method will return null if the content has not yet been written by the
* writer or if the output stream is still open.
*
* @return Returns a reader onto the underlying content that this writer
* will or has written to
* @throws ContentIOException
*/
public ContentReader getReader() throws ContentIOException;
/**
* Convenience method to find out if this writer has been closed.
* Once closed, the content can no longer be written to and it become possible
* to get readers onto the written content.
*
* @return Return true if the content output stream has been used and closed
* otherwise false.
*/
public boolean isClosed();
/**
* Provides low-level access to write to repository content.
* <p>
* The channel returned to the client should remain open (subject to timeouts)
* until closed by the client. All lock detection, read-only access and other
* concurrency issues are dealt with during this operation. It remains
* possible that implementations will throw exceptions when the channel is closed.
* <p>
* The stream will notify any listeners according to the listener interface.
*
* @return Returns a channel with which to write content
* @throws ContentIOException
*/
public WritableByteChannel getWritableChannel() throws ContentIOException;
/**
* Get a stream to write to the underlying channel.
*
* @return Returns an output stream onto the underlying channel
* @throws ContentIOException
*
* @see #getWritableChannel()
*/
public OutputStream getContentOutputStream() throws ContentIOException;
/**
* Copies content from the reader.
* <p>
* All resources will be closed automatically.
*
* @param reader the reader acting as the source of the content
* @throws ContentIOException
*
* @see #getWritableChannel()
*/
public void putContent(ContentReader reader) throws ContentIOException;
/**
* Puts content to the repository
* <p>
* All resources will be closed automatically.
*
* @param is the input stream from which the content will be read
* @throws ContentIOException
*
* @see #getWritableChannel()
*/
public void putContent(InputStream is) throws ContentIOException;
/**
* Puts content to the repository direct from file
* <p>
* All resources will be closed automatically.
*
* @param file the file to load the content from
* @throws ContentIOException
*
* @see #getWritableChannel()
*/
public void putContent(File file) throws ContentIOException;
/**
* Puts content to the repository direct from <code>String</code>.
* <p>
* If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used
* otherwise the default system <tt>String</tt> to <tt>byte[]</tt> conversion
* will be used.
* <p>
* All resources will be closed automatically.
*
* @param content a string representation of the content
* @throws ContentIOException
*
* @see #getWritableChannel()
* @see String#getBytes(java.lang.String)
*/
public void putContent(String content) throws ContentIOException;
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.service.namespace.QName;
/**
* Node operations service interface.
* <p>
* This interface provides methods to copy nodes within and across workspaces and to
* update the state of a node, with that of another node, within and across workspaces.
*
* @author Roy Wetherall
*/
public interface CopyService
{
/**
* Creates a copy of the given node.
* <p>
* If the new node resides in a different workspace the new node will
* have the same id.
* <p>
* If the new node resides in the same workspace then
* the new node will have the Copy aspect applied to it which will
* reference the origional node.
* <p>
* The aspects applied to source node will also be applied to destination node
* and all the property value will be duplicated accordingly. This is with the
* exception of the aspects that have been marked as having 'Non-Transferable State'.
* In this case the aspect will be applied to the copy, but the properties will take
* on the default values.
* <p>
* Child associations are copied onto the destination node. If the child of
* copied association is not present in the destination workspace the child
* association is not copied. This is unless is has been specfied that the
* children of the source node should also be copied.
* <p>
* Target associations are copied to the destination node. If the target of the
* association is not present in the destination workspace then the association is
* not copied.
* <p>
* Source association are not copied.
*
* @param sourceNodeRef the node reference used as the source of the copy
* @param destinationParent the intended parent of the new node
* @param destinationAssocTypeQName the type of the new child assoc
* @param destinationQName the qualified name of the child association from the
* parent to the new node
*
* @return the new node reference
*/
public NodeRef copy(
NodeRef sourceNodeRef,
NodeRef destinationParent,
QName destinationAssocTypeQName,
QName destinationQName,
boolean copyChildren);
/**
* By default children of the source node are not copied.
*
* @see NodeCopyService#copy(NodeRef, NodeRef, QName, QName, boolean)
*
* @param sourceNodeRef the node reference used as the source of the copy
* @param destinationParent the intended parent of the new node
* @param destinationAssocTypeQName the type of the new child assoc
* @param destinationQName the qualified name of the child association from the
* parent to the new node
* @return the new node reference
*/
public NodeRef copy(
NodeRef sourceNodeRef,
NodeRef destinationParent,
QName destinationAssocTypeQName,
QName destinationQName);
/**
* Copies the state of one node on top of another.
* <p>
* The state of destination node is overlayed with the state of the
* source node. Any conflicts are resolved by setting the state to
* that of the source node.
* <p>
* If data (for example an association) does not exist on the source
* node, but does exist on the detination node this data is NOT deleted
* from the destination node.
* <p>
* Child associations and target associations are updated on the destination
* based on the current state of the source node.
* <p>
* If the node that either a child or target association points to on the source
* node is not present in the destinations workspace then the association is not
* updated to the destination node.
* <p>
* All aspects found on the source node are applied to the destination node where
* missing. The properties of the apects are updated accordingly except in the case
* where the aspect has been marked as having 'Non-Transferable State'. In this case
* aspect properties will take on the values already assigned to them in the
* destination node.
*
* @param sourceNodeRef the source node reference
* @param destinationNodeRef the destination node reference
*/
public void copy(NodeRef sourceNodeRef, NodeRef destinationNodeRef);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Nodes operations service exception class.
*
* @author Roy Wetherall
*/
public class CopyServiceException extends RuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3256727273112614964L;
/**
* Constructor
*/
public CopyServiceException()
{
super();
}
/**
* Constructor
*
* @param message the error message
*/
public CopyServiceException(String message)
{
super(message);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.repo.domain.ChildAssoc;
/**
* Thrown when a cyclic parent-child relationship is detected.
*
* @author Derek Hulley
*/
public class CyclicChildRelationshipException extends RuntimeException
{
private static final long serialVersionUID = 3545794381924874036L;
private ChildAssoc assoc;
public CyclicChildRelationshipException(String msg, ChildAssoc assoc)
{
super(msg);
this.assoc = assoc;
}
public ChildAssoc getAssoc()
{
return assoc;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* A marker interface for entity reference classes.
* <p>
* This is used primarily as a means of ensuring type safety in collections
* of mixed type references.
*
* @see org.alfresco.service.cmr.repository.NodeService#removeChildren(NodeRef, QName)
*
* @author Derek Hulley
*/
public interface EntityRef
{
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Thrown when an operation cannot be performed because the<b>child association</b>
* reference no longer exists.
*
* @author Derek Hulley
*/
public class InvalidChildAssociationRefException extends RuntimeException
{
private static final long serialVersionUID = -7493054268618534572L;
private ChildAssociationRef childAssociationRef;
public InvalidChildAssociationRefException(ChildAssociationRef childAssociationRef)
{
this(null, childAssociationRef);
}
public InvalidChildAssociationRefException(String msg, ChildAssociationRef childAssociationRef)
{
super(msg);
this.childAssociationRef = childAssociationRef;
}
/**
* @return Returns the offending child association reference
*/
public ChildAssociationRef getChildAssociationRef()
{
return childAssociationRef;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Thrown when an operation cannot be performed because the <b>node</b> reference
* no longer exists.
*
* @author Derek Hulley
*/
public class InvalidNodeRefException extends RuntimeException
{
private static final long serialVersionUID = 3689345520586273336L;
private NodeRef nodeRef;
public InvalidNodeRefException(NodeRef nodeRef)
{
this(null, nodeRef);
}
public InvalidNodeRefException(String msg, NodeRef nodeRef)
{
super(msg);
this.nodeRef = nodeRef;
}
/**
* @return Returns the offending node reference
*/
public NodeRef getNodeRef()
{
return nodeRef;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Thrown when an operation cannot be performed because the <b>store</b> reference
* no longer exists.
*
* @author Derek Hulley
*/
public class InvalidStoreRefException extends AbstractStoreException
{
private static final long serialVersionUID = 3258126938479409463L;
public InvalidStoreRefException(StoreRef storeRef)
{
super(storeRef);
}
public InvalidStoreRefException(String msg, StoreRef storeRef)
{
super(msg, storeRef);
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* This service interface provides support for Mimetypes.
*
* @author Derek Hulley
*
*/
public interface MimetypeService
{
/**
* Get the extension for the specified mimetype
*
* @param mimetype a valid mimetype
* @return Returns the default extension for the mimetype
* @throws AlfrescoRuntimeException if the mimetype doesn't exist
*/
public String getExtension(String mimetype);
/**
* Get all human readable mimetype descriptions indexed by mimetype extension
*
* @return the map of displays indexed by extension
*/
public Map<String, String> getDisplaysByExtension();
/**
* Get all human readable mimetype descriptions indexed by mimetype
*
* @return the map of displays indexed by mimetype
*/
public Map<String, String> getDisplaysByMimetype();
/**
* Get all mimetype extensions indexed by mimetype
*
* @return the map of extension indexed by mimetype
*/
public Map<String, String> getExtensionsByMimetype();
/**
* Get all mimetypes indexed by extension
*
* @return the map of mimetypes indexed by extension
*/
public Map<String, String> getMimetypesByExtension();
/**
* Get all mimetypes
*
* @return all mimetypes
*/
public List<String> getMimetypes();
/**
* Provides a non-null best guess of the appropriate mimetype given a
* filename.
*
* @param filename the name of the file with an optional file extension
* @return Returns the best guess mimetype or the mimetype for
* straight binary files if no extension could be found.
*/
public String guessMimetype(String filename);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.text.MessageFormat;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Thrown when a transformation request cannot be honoured due to
* no transformers being present for the requested transformation.
*
* @author Derek Hulley
*/
public class NoTransformerException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = 3689067335554183222L;
private static final MessageFormat MSG =
new MessageFormat("No transformation exists between mimetypes {0} and {1}");
private String sourceMimetype;
private String targetMimetype;
/**
* @param sourceMimetype the attempted source mimetype
* @param targetMimetype the attempted target mimetype
*/
public NoTransformerException(String sourceMimetype, String targetMimetype)
{
super(MSG.format(new Object[] {sourceMimetype, targetMimetype}));
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
}
public String getSourceMimetype()
{
return sourceMimetype;
}
public String getTargetMimetype()
{
return targetMimetype;
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Reference to a node
*
* @author Derek Hulley
*/
public final class NodeRef implements EntityRef, Serializable
{
private static final long serialVersionUID = 3760844584074227768L;
private static final String URI_FILLER = "/";
private final StoreRef storeRef;
private final String id;
/**
* Construct a Node Reference from a Store Reference and Node Id
*
* @param storeRef store reference
* @param id the manually assigned identifier of the node
*/
public NodeRef(StoreRef storeRef, String id)
{
if (storeRef == null)
{
throw new IllegalArgumentException(
"Store reference may not be null");
}
if (id == null)
{
throw new IllegalArgumentException("Node id may not be null");
}
this.storeRef = storeRef;
this.id = id;
}
/**
* Construct a Node Reference from a string representation of a Node Reference.
* <p>
* The string representation of a Node Reference is as follows:
* <p>
* <pre><storeref>/<nodeId></pre>
*
* @param nodeRef the string representation of a node ref
*/
public NodeRef(String nodeRef)
{
int lastForwardSlash = nodeRef.lastIndexOf('/');
if(lastForwardSlash == -1)
{
throw new AlfrescoRuntimeException("Invalid node ref - does not contain forward slash: " + nodeRef);
}
this.storeRef = new StoreRef(nodeRef.substring(0, lastForwardSlash));
this.id = nodeRef.substring(lastForwardSlash+1);
}
public String toString()
{
return storeRef.toString() + URI_FILLER + id;
}
/**
* Override equals for this ref type
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj instanceof NodeRef)
{
NodeRef that = (NodeRef) obj;
return (this.id.equals(that.id)
&& this.storeRef.equals(that.storeRef));
}
else
{
return false;
}
}
/**
* Hashes on ID alone. As the number of copies of a particular node will be minimal, this is acceptable
*/
public int hashCode()
{
return id.hashCode();
}
/**
* @return The StoreRef part of this reference
*/
public final StoreRef getStoreRef()
{
return storeRef;
}
/**
* @return The Node Id part of this reference
*/
public final String getId()
{
return id;
}
/**
* Helper class to convey the status of a <b>node</b>.
*
* @author Derek Hulley
*/
public static class Status
{
private final String changeTxnId;
private final boolean deleted;
public Status(String changeTxnId, boolean deleted)
{
this.changeTxnId = changeTxnId;
this.deleted = deleted;
}
/**
* @return Returns the ID of the last transaction to change the node
*/
public String getChangeTxnId()
{
return changeTxnId;
}
/**
* @return Returns true if the node has been deleted, otherwise false
*/
public boolean isDeleted()
{
return deleted;
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import junit.framework.TestCase;
/**
* @see org.alfresco.service.cmr.repository.NodeRef
*
* @author Derek Hulley
*/
public class NodeRefTest extends TestCase
{
public NodeRefTest(String name)
{
super(name);
}
public void testStoreRef() throws Exception
{
StoreRef storeRef = new StoreRef("ABC", "123");
assertEquals("toString failure", "ABC://123", storeRef.toString());
StoreRef storeRef2 = new StoreRef(storeRef.getProtocol(), storeRef
.getIdentifier());
assertEquals("equals failure", storeRef, storeRef2);
}
public void testNodeRef() throws Exception
{
StoreRef storeRef = new StoreRef("ABC", "123");
NodeRef nodeRef = new NodeRef(storeRef, "456");
assertEquals("toString failure", "ABC://123/456", nodeRef.toString());
NodeRef nodeRef2 = new NodeRef(storeRef, "456");
assertEquals("equals failure", nodeRef, nodeRef2);
}
}

View File

@@ -0,0 +1,478 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
/**
* Interface for public and internal <b>node</b> and <b>store</b> operations.
*
* @author Derek Hulley
*/
public interface NodeService
{
/**
* Gets a list of all available node store references
*
* @return Returns a list of store references
*/
public List<StoreRef> getStores();
/**
* Create a new store for the given protocol and identifier. The implementation
* may create the store in any number of locations, including a database or
* Subversion.
*
* @param protocol the implementation protocol
* @param identifier the protocol-specific identifier
* @return Returns a reference to the store
* @throws StoreExistsException
*/
public StoreRef createStore(String protocol, String identifier) throws StoreExistsException;
/**
* @param storeRef a reference to the store to look for
* @return Returns true if the store exists, otherwise false
*/
public boolean exists(StoreRef storeRef);
/**
* @param nodeRef a reference to the node to look for
* @return Returns true if the node exists, otherwise false
*/
public boolean exists(NodeRef nodeRef);
/**
* Gets the ID of the last transaction that caused the node to change. This includes
* deletions, so it is possible that the node being referenced no longer exists.
* If the node never existed, then null is returned.
*
* @param nodeRef a reference to a current or previously existing node
* @return Returns the status of the node, or null if the node never existed
*/
public NodeRef.Status getNodeStatus(NodeRef nodeRef);
/**
* @param storeRef a reference to an existing store
* @return Returns a reference to the root node of the store
* @throws InvalidStoreRefException if the store could not be found
*/
public NodeRef getRootNode(StoreRef storeRef) throws InvalidStoreRefException;
/**
* @see #createNode(NodeRef, QName, QName, QName, Map)
*/
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName)
throws InvalidNodeRefException, InvalidTypeException;
/**
* Creates a new, non-abstract, real node as a primary child of the given parent node.
*
* @param parentRef the parent node
* @param assocTypeQName the type of the association to create. This is used
* for verification against the data dictionary.
* @param assocQName the qualified name of the association
* @param nodeTypeQName a reference to the node type
* @param properties optional map of properties to keyed by their qualified names
* @return Returns a reference to the newly created child association
* @throws InvalidNodeRefException if the parent reference is invalid
* @throws InvalidTypeException if the node type reference is not recognised
*
* @see org.alfresco.service.cmr.dictionary.DictionaryService
*/
public ChildAssociationRef createNode(
NodeRef parentRef,
QName assocTypeQName,
QName assocQName,
QName nodeTypeQName,
Map<QName, Serializable> properties)
throws InvalidNodeRefException, InvalidTypeException;
/**
* Moves the primary location of the given node.
* <p>
* This involves changing the node's primary parent and possibly the name of the
* association referencing it.
*
* @param nodeToMoveRef the node to move
* @param newParentRef the new parent of the moved node
* @param assocTypeQName the type of the association to create. This is used
* for verification against the data dictionary.
* @param assocQName the qualified name of the new child association
* @return Returns a reference to the newly created child association
* @throws InvalidNodeRefException if either the parent node or move node reference is invalid
* @throws CyclicChildRelationshipException if the child partakes in a cyclic relationship after the add
*
* @see #getPrimaryParent(NodeRef)
*/
public ChildAssociationRef moveNode(
NodeRef nodeToMoveRef,
NodeRef newParentRef,
QName assocTypeQName,
QName assocQName)
throws InvalidNodeRefException;
/**
* Set the ordering index of the child association. This affects the ordering of
* of the return values of methods that return a set of children or child
* associations.
*
* @param childAssocRef the child association that must be moved in the order
* @param index an arbibrary index that will affect the return order
*
* @see #getChildAssocs(NodeRef)
* @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern)
* @see ChildAssociationRef#getNthSibling()
*/
public void setChildAssociationIndex(
ChildAssociationRef childAssocRef,
int index)
throws InvalidChildAssociationRefException;
/**
* @param nodeRef
* @return Returns the type name
* @throws InvalidNodeRefException if the node could not be found
*
* @see org.alfresco.service.cmr.dictionary.DictionaryService
*/
public QName getType(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* Re-sets the type of the node. Can be called in order specialise a node to a sub-type.
*
* This should be used with caution since calling it changes the type of the node and thus
* implies a different set of aspects, properties and associations. It is the calling codes
* responsibility to ensure that the node is in a approriate state after changing the type.
*
* @param nodeRef the node reference
* @param typeQName the type QName
*
* @since 1.1
*/
public void setType(NodeRef nodeRef, QName typeQName) throws InvalidNodeRefException;
/**
* Applies an aspect to the given node. After this method has been called,
* the node with have all the aspect-related properties present
*
* @param nodeRef
* @param aspectTypeQName the aspect to apply to the node
* @param aspectProperties a minimum of the mandatory properties required for
* the aspect
* @throws InvalidNodeRefException
* @throws InvalidAspectException if the class reference is not to a valid aspect
*
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getAspect(QName)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getProperties()
*/
public void addAspect(
NodeRef nodeRef,
QName aspectTypeQName,
Map<QName, Serializable> aspectProperties)
throws InvalidNodeRefException, InvalidAspectException;
/**
* Remove an aspect and all related properties from a node
*
* @param nodeRef
* @param aspectTypeQName the type of aspect to remove
* @throws InvalidNodeRefException if the node could not be found
* @throws InvalidAspectException if the the aspect is unknown or if the
* aspect is mandatory for the <b>class</b> of the <b>node</b>
*/
public void removeAspect(NodeRef nodeRef, QName aspectTypeQName)
throws InvalidNodeRefException, InvalidAspectException;
/**
* Determines if a given aspect is present on a node. Aspects may only be
* removed if they are <b>NOT</b> mandatory.
*
* @param nodeRef
* @param aspectRef
* @return Returns true if the aspect has been applied to the given node,
* otherwise false
* @throws InvalidNodeRefException if the node could not be found
* @throws InvalidAspectException if the aspect reference is invalid
*/
public boolean hasAspect(NodeRef nodeRef, QName aspectRef)
throws InvalidNodeRefException, InvalidAspectException;
/**
* @param nodeRef
* @return Returns a set of all aspects applied to the node, including mandatory
* aspects
* @throws InvalidNodeRefException if the node could not be found
*/
public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* Deletes the given node.
* <p>
* All associations (both children and regular node associations)
* will be deleted, and where the given node is the primary parent,
* the children will also be cascade deleted.
*
* @param nodeRef reference to a node within a store
* @throws InvalidNodeRefException if the reference given is invalid
*/
public void deleteNode(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* Makes a parent-child association between the given nodes. Both nodes must belong to the same store.
* <p>
*
*
* @param parentRef
* @param childRef
* @param assocTypeQName the qualified name of the association type as defined in the datadictionary
* @param qname the qualified name of the association
* @return Returns a reference to the newly created child association
* @throws InvalidNodeRefException if the parent or child nodes could not be found
* @throws CyclicChildRelationshipException if the child partakes in a cyclic relationship after the add
*/
public ChildAssociationRef addChild(
NodeRef parentRef,
NodeRef childRef,
QName assocTypeQName,
QName qname) throws InvalidNodeRefException;
/**
* Severs all parent-child relationships between two nodes.
* <p>
* The child node will be cascade deleted if one of the associations was the
* primary association, i.e. the one with which the child node was created.
*
* @param parentRef the parent end of the association
* @param childRef the child end of the association
* @return Returns a collection of deleted entities - both associations and node references.
* @throws InvalidNodeRefException if the parent or child nodes could not be found
*/
public void removeChild(NodeRef parentRef, NodeRef childRef) throws InvalidNodeRefException;
/**
* @param nodeRef
* @return Returns all properties keyed by their qualified name
* @throws InvalidNodeRefException if the node could not be found
*/
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* @param nodeRef
* @param qname the qualified name of the property
* @return Returns the value of the property, or null if not yet set
* @throws InvalidNodeRefException if the node could not be found
*/
public Serializable getProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException;
/**
* Set the values of all properties to be an <code>Serializable</code> instances.
* The properties given must still fulfill the requirements of the class and
* aspects relevant to the node.
* <p>
* <b>NOTE:</b> Null values <u>are</u> allowed.
*
* @param nodeRef
* @param properties all the properties of the node keyed by their qualified names
* @throws InvalidNodeRefException if the node could not be found
*/
public void setProperties(NodeRef nodeRef, Map<QName, Serializable> properties) throws InvalidNodeRefException;
/**
* Sets the value of a property to be any <code>Serializable</code> instance.
* To remove a property value, use {@link #getProperties(NodeRef)}, remove the
* value and call {@link #setProperties(NodeRef, Map<QName,Serializable>)}.
* <p>
* <b>NOTE:</b> Null values <u>are</u> allowed.
*
* @param nodeRef
* @param qname the fully qualified name of the property
* @param propertyValue the value of the property - never null
* @throws InvalidNodeRefException if the node could not be found
*/
public void setProperty(NodeRef nodeRef, QName qname, Serializable value) throws InvalidNodeRefException;
/**
* @param nodeRef the child node
* @return Returns a list of all parent-child associations that exist where the given
* node is the child
* @throws InvalidNodeRefException if the node could not be found
*
* @see #getParentAssocs(NodeRef, QNamePattern, QNamePattern)
*/
public List<ChildAssociationRef> getParentAssocs(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* Gets all parent associations where the pattern of the association qualified
* name is a match
* <p>
* The resultant list is ordered by (a) explicit index and (b) association creation time.
*
* @param nodeRef the child node
* @param typeQNamePattern the pattern that the type qualified name of the association must match
* @param qnamePattern the pattern that the qnames of the assocs must match
* @return Returns a list of all parent-child associations that exist where the given
* node is the child
* @throws InvalidNodeRefException if the node could not be found
*
* @see ChildAssociationRef#getNthSibling()
* @see #setChildAssociationIndex(ChildAssociationRef, int)
* @see QName
* @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL
*/
public List<ChildAssociationRef> getParentAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern)
throws InvalidNodeRefException;
/**
* Get all child associations of the given node.
* <p>
* The resultant list is ordered by (a) explicit index and (b) association creation time.
*
* @param nodeRef the parent node - usually a <b>container</b>
* @return Returns a collection of <code>ChildAssocRef</code> instances. If the
* node is not a <b>container</b> then the result will be empty.
* @throws InvalidNodeRefException if the node could not be found
*
* @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern)
* @see #setChildAssociationIndex(ChildAssociationRef, int)
* @see ChildAssociationRef#getNthSibling()
*/
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* Gets all child associations where the pattern of the association qualified
* name is a match.
*
* @param nodeRef the parent node - usually a <b>container</b>
* @param typeQNamePattern the pattern that the type qualified name of the association must match
* @param qnamePattern the pattern that the qnames of the assocs must match
* @return Returns a list of <code>ChildAssocRef</code> instances. If the
* node is not a <b>container</b> then the result will be empty.
* @throws InvalidNodeRefException if the node could not be found
*
* @see QName
* @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL
*/
public List<ChildAssociationRef> getChildAssocs(
NodeRef nodeRef,
QNamePattern typeQNamePattern,
QNamePattern qnamePattern)
throws InvalidNodeRefException;
/**
* Fetches the primary parent-child relationship.
* <p>
* For a root node, the parent node reference will be null.
*
* @param nodeRef
* @return Returns the primary parent-child association of the node
* @throws InvalidNodeRefException if the node could not be found
*/
public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException;
/**
*
* @param sourceRef a reference to a <b>real</b> node
* @param targetRef a reference to a node
* @param assocTypeQName the qualified name of the association type
* @return Returns a reference to the new association
* @throws InvalidNodeRefException if either of the nodes could not be found
* @throws AssociationExistsException
*/
public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
throws InvalidNodeRefException, AssociationExistsException;
/**
*
* @param sourceRef the associaton source node
* @param targetRef the association target node
* @param assocTypeQName the qualified name of the association type
* @throws InvalidNodeRefException if either of the nodes could not be found
*/
public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName)
throws InvalidNodeRefException;
/**
* Fetches all associations <i>from</i> the given source where the associations'
* qualified names match the pattern provided.
*
* @param sourceRef the association source
* @param qnamePattern the association qname pattern to match against
* @return Returns a list of <code>NodeAssocRef</code> instances for which the
* given node is a source
* @throws InvalidNodeRefException if the source node could not be found
*
* @see QName
* @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL
*/
public List<AssociationRef> getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern)
throws InvalidNodeRefException;
/**
* Fetches all associations <i>to</i> the given target where the associations'
* qualified names match the pattern provided.
*
* @param targetRef the association target
* @param qnamePattern the association qname pattern to match against
* @return Returns a list of <code>NodeAssocRef</code> instances for which the
* given node is a target
* @throws InvalidNodeRefException
*
* @see QName
* @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL
*/
public List<AssociationRef> getSourceAssocs(NodeRef targetRef, QNamePattern qnamePattern)
throws InvalidNodeRefException;
/**
* The root node has an entry in the path(s) returned. For this reason, there
* will always be <b>at least one</b> path element in the returned path(s).
* The first element will have a null parent reference and qname.
*
* @param nodeRef
* @return Returns the path to the node along the primary node path
* @throws InvalidNodeRefException if the node could not be found
*
* @see #getPaths(NodeRef, boolean)
*/
public Path getPath(NodeRef nodeRef) throws InvalidNodeRefException;
/**
* The root node has an entry in the path(s) returned. For this reason, there
* will always be <b>at least one</b> path element in the returned path(s).
* The first element will have a null parent reference and qname.
*
* @param nodeRef
* @param primaryOnly true if only the primary path must be retrieved. If true, the
* result will have exactly one entry.
* @return Returns a List of all possible paths to the given node
* @throws InvalidNodeRefException if the node could not be found
*/
public List<Path> getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException;
}

View File

@@ -0,0 +1,580 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.ISO9075;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* Representation of a simple path e.g.
* <b><pre>
* /x/y/z
* </pre></b>
* In the above example, there will be <b>4</b> elements, the first being a reference
* to the root node, followed by qname elements for <b>x</b>, <b>x</b> and <b>z</b>.
* <p>
* Methods and constructors are available to construct a <code>Path</code> instance
* from a path string or by building the path incrementally, including the ability to
* append and prepend path elements.
* <p>
* Path elements supported:
* <ul>
* <li><b>/{namespace}name</b> fully qualified element</li>
* <li><b>/name</b> element using default namespace</li>
* <li><b>/{namespace}name[n]</b> nth sibling</li>
* <li><b>/name[n]</b> nth sibling using default namespace</li>
* <li><b>/descendant-or-self::node()</b> descendent or self</li>
* <li><b>/.</b> self</li>
* <li><b>/..</b> parent</li>
* </ul>
*
* @author Derek Hulley
*/
public final class Path implements Iterable<Path.Element>, Serializable
{
private static final long serialVersionUID = 3905520514524328247L;
private LinkedList<Element> elements;
public Path()
{
// use linked list so as random access is not required, but both prepending and appending is
elements = new LinkedList<Element>();
}
/**
* @return Returns a typed iterator over the path elements
*/
public Iterator<Path.Element> iterator()
{
return elements.iterator();
}
/**
* Add a path element to the beginning of the path. This operation is useful in cases where
* a path is built by traversing up a hierarchy.
*
* @param pathElement
* @return Returns this instance of the path
*/
public Path prepend(Path.Element pathElement)
{
elements.addFirst(pathElement);
return this;
}
/**
* Merge the given path into the beginning of this path.
*
* @param path
* @return Returns this instance of the path
*/
public Path prepend(Path path)
{
elements.addAll(0, path.elements);
return this;
}
/**
* Appends a path element to the end of the path
*
* @param pathElement
* @return Returns this instance of the path
*/
public Path append(Path.Element pathElement)
{
elements.addLast(pathElement);
return this;
}
/**
* Append the given path of this path.
*
* @param path
* @return Returns this instance of the path
*/
public Path append(Path path)
{
elements.addAll(path.elements);
return this;
}
/**
* @return Returns the first element in the path or null if the path is empty
*/
public Element first()
{
return elements.getFirst();
}
/**
* @return Returns the last element in the path or null if the path is empty
*/
public Element last()
{
return elements.getLast();
}
public int size()
{
return elements.size();
}
public Element get(int n)
{
return elements.get(n);
}
/**
* @return Returns a string path made up of the component elements of this instance
*/
public String toString()
{
StringBuilder sb = new StringBuilder(128);
for (Element element : elements)
{
if((sb.length() > 1) || ((sb.length() == 1) && (sb.charAt(0) != '/')))
{
sb.append("/");
}
sb.append(element.getElementString());
}
return sb.toString();
}
/**
* @return Returns a string path made up of the component elements of this instance (prefixed where appropriate)
*/
public String toPrefixString(NamespacePrefixResolver resolver)
{
StringBuilder sb = new StringBuilder(128);
for (Element element : elements)
{
if((sb.length() > 1) || ((sb.length() == 1) && (sb.charAt(0) != '/')))
{
sb.append("/");
}
sb.append(element.getPrefixedString(resolver));
}
return sb.toString();
}
/**
* Return the human readable form of the specified node Path. Slow version of the method
* that extracts the name of each node in the Path from the supplied NodeService.
*
* @return human readable form of the Path excluding the final element
*/
public String toDisplayPath(NodeService nodeService)
{
StringBuilder buf = new StringBuilder(64);
for (int i=0; i<elements.size()-1; i++)
{
String elementString = null;
Element element = elements.get(i);
if (element instanceof ChildAssocElement)
{
ChildAssociationRef elementRef = ((ChildAssocElement)element).getRef();
if (elementRef.getParentRef() != null)
{
Serializable nameProp = null;
try
{
nameProp = nodeService.getProperty(elementRef.getChildRef(), ContentModel.PROP_NAME);
}
catch (AccessDeniedException err)
{
// unable to access this property on the path - so we cannot display it's name
}
if (nameProp != null)
{
// use the name property if we find it
elementString = nameProp.toString();
}
else
{
// revert to using QName if not found
elementString = elementRef.getQName().getLocalName();
}
}
}
else
{
elementString = element.getElementString();
}
if (elementString != null)
{
buf.append("/");
buf.append(elementString);
}
}
return buf.toString();
}
/**
* Return a new Path representing this path to the specified depth
*
* @param depth the path depth (0 based)
* @return the sub-path
*/
public Path subPath(int depth)
{
return subPath(0, depth);
}
/**
* Return a new Path representing this path to the specified depth
*
* @param depth the path depth (0 based)
* @return the sub-path
*/
public Path subPath(int start, int end)
{
if (start < 0 || start > (elements.size() -1))
{
throw new IndexOutOfBoundsException("Start index " + start + " must be between 0 and " + (elements.size() -1));
}
if (end < 0 || end > (elements.size() -1))
{
throw new IndexOutOfBoundsException("End index " + end + " must be between 0 and " + (elements.size() -1));
}
if (end < start)
{
throw new IndexOutOfBoundsException("End index " + end + " cannot be before start index " + start);
}
Path subPath = new Path();
for (int i = start; i <= end; i++)
{
subPath.append(this.get(i));
}
return subPath;
}
/**
* Override equals to check equality of Path instances
*/
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof Path))
{
return false;
}
Path other = (Path)o;
return this.elements.equals(other.elements);
}
/**
* Override hashCode to check hash equality of Path instances
*/
public int hashCode()
{
return elements.hashCode();
}
/**
* Represents a path element.
* <p>
* In <b>/x/y/z</b>, elements are <b>x</b>, <b>y</b> and <b>z</b>.
*/
public abstract static class Element implements Serializable
{
/**
* @return Returns the path element portion including leading '/' and never null
*/
public abstract String getElementString();
/**
* @param resolver namespace prefix resolver
* @return the path element portion (with namespaces converted to prefixes)
*/
public String getPrefixedString(NamespacePrefixResolver resolver)
{
return getElementString();
}
/**
* @see #getElementString()
*/
public String toString()
{
return getElementString();
}
}
/**
* Represents a qualified path between a parent and a child node,
* including the sibling to retrieve e.g. <b>/{namespace}name[5]</b>
*/
public static class ChildAssocElement extends Element
{
private static final long serialVersionUID = 3689352104636790840L;
private ChildAssociationRef ref;
/**
* @param ref a reference to the specific parent-child association
*/
public ChildAssocElement(ChildAssociationRef ref)
{
this.ref = ref;
}
@Override
public String getElementString()
{
return createElementString(null);
}
@Override
public String getPrefixedString(NamespacePrefixResolver resolver)
{
return createElementString(resolver);
}
public ChildAssociationRef getRef()
{
return ref;
}
@Override
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof ChildAssocElement))
{
return false;
}
ChildAssocElement other = (ChildAssocElement)o;
return this.ref.equals(other.ref);
}
@Override
public int hashCode()
{
return ref.hashCode();
}
private String createElementString(NamespacePrefixResolver resolver)
{
StringBuilder sb = new StringBuilder(32);
if (ref.getParentRef() == null)
{
sb.append("/");
}
else
{
// a parent is present
sb.append(resolver == null ? ISO9075.getXPathName(ref.getQName()) : ISO9075.getXPathName(ref.getQName(), resolver));
}
if (ref.getNthSibling() > -1)
{
sb.append("[").append(ref.getNthSibling()).append("]");
}
return sb.toString();
}
}
/**
* Represents a qualified path to an attribute,
* including the sibling for repeated properties/attributes to retrieve e.g. <b>/@{namespace}name[5]</b>
*/
public static class AttributeElement extends Element
{
private static final long serialVersionUID = 3256727281668863544L;
private QName attribute;
private int position = -1;
/**
* @param ref a reference to the specific parent-child association
*/
public AttributeElement(QName attribute)
{
this.attribute = attribute;
}
public AttributeElement(QName attribute, int position)
{
this(attribute);
this.position = position;
}
@Override
public String getElementString()
{
return createElementString(null);
}
@Override
public String getPrefixedString(NamespacePrefixResolver resolver)
{
return createElementString(resolver);
}
private String createElementString(NamespacePrefixResolver resolver)
{
StringBuilder sb = new StringBuilder(32);
sb.append("@").append(resolver == null ? ISO9075.getXPathName(attribute) : ISO9075.getXPathName(attribute, resolver));
if (position > -1)
{
sb.append("[").append(position).append("]");
}
return sb.toString();
}
public QName getQName()
{
return attribute;
}
public int position()
{
return position;
}
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof AttributeElement))
{
return false;
}
AttributeElement other = (AttributeElement)o;
return this.getQName().equals(other.getQName()) && (this.position() == other.position());
}
public int hashCode()
{
return getQName().hashCode()*32 + position();
}
}
/**
* Represents the <b>//</b> or <b>/descendant-or-self::node()</b> xpath element
*/
public static class DescendentOrSelfElement extends Element
{
private static final long serialVersionUID = 3258410616875005237L;
public String getElementString()
{
return "descendant-or-self::node()";
}
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof DescendentOrSelfElement))
{
return false;
}
return true;
}
public int hashCode()
{
return "descendant-or-self::node()".hashCode();
}
}
/**
* Represents the <b>/.</b> xpath element
*/
public static class SelfElement extends Element
{
private static final long serialVersionUID = 3834311739151300406L;
public String getElementString()
{
return ".";
}
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof SelfElement))
{
return false;
}
return true;
}
public int hashCode()
{
return ".".hashCode();
}
}
/**
* Represents the <b>/..</b> xpath element
*/
public static class ParentElement extends Element
{
private static final long serialVersionUID = 3689915080477456179L;
public String getElementString()
{
return "..";
}
public boolean equals(Object o)
{
if(o == this)
{
return true;
}
if(!(o instanceof ParentElement))
{
return false;
}
return true;
}
public int hashCode()
{
return "..".hashCode();
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.service.namespace.QName;
import junit.framework.TestCase;
/**
* @see org.alfresco.service.cmr.repository.Path
*
* @author Derek Hulley
*/
public class PathTest extends TestCase
{
private Path absolutePath;
private Path relativePath;
private QName typeQName;
private QName qname;
private StoreRef storeRef;
private NodeRef parentRef;
private NodeRef childRef;
public PathTest(String name)
{
super(name);
}
public void setUp() throws Exception
{
super.setUp();
absolutePath = new Path();
relativePath = new Path();
typeQName = QName.createQName("http://www.alfresco.org/PathTest/1.0", "testType");
qname = QName.createQName("http://www.google.com", "documentx");
storeRef = new StoreRef("x", "y");
parentRef = new NodeRef(storeRef, "P");
childRef = new NodeRef(storeRef, "C");
}
public void testQNameElement() throws Exception
{
// plain
Path.Element element = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef));
assertEquals("Element string incorrect",
qname.toString(),
element.getElementString());
// sibling
element = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef, true, 5));
assertEquals("Element string incorrect", "{http://www.google.com}documentx[5]", element.getElementString());
}
public void testElementTypes() throws Exception
{
Path.Element element = new Path.DescendentOrSelfElement();
assertEquals("DescendentOrSelf element incorrect",
"descendant-or-self::node()",
element.getElementString());
element = new Path.ParentElement();
assertEquals("Parent element incorrect", "..", element.getElementString());
element = new Path.SelfElement();
assertEquals("Self element incorrect", ".", element.getElementString());
}
public void testAppendingAndPrepending() throws Exception
{
Path.Element element0 = new Path.ChildAssocElement(new ChildAssociationRef(null, null, null, parentRef));
Path.Element element1 = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef, true, 4));
Path.Element element2 = new Path.DescendentOrSelfElement();
Path.Element element3 = new Path.ParentElement();
Path.Element element4 = new Path.SelfElement();
// append them all to the path
absolutePath.append(element0).append(element1).append(element2).append(element3).append(element4);
relativePath.append(element1).append(element2).append(element3).append(element4);
// check
assertEquals("Path appending didn't work",
"/{http://www.google.com}documentx[4]/descendant-or-self::node()/../.",
absolutePath.toString());
// copy the path
Path copy = new Path();
copy.append(relativePath).append(relativePath);
// check
assertEquals("Path appending didn't work",
relativePath.toString() + "/" + relativePath.toString(),
copy.toString());
// prepend
relativePath.prepend(element2);
// check
assertEquals("Prepending didn't work",
"descendant-or-self::node()/{http://www.google.com}documentx[4]/descendant-or-self::node()/../.",
relativePath.toString());
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Thrown when an operation cannot be performed because the <b>store</b> reference
* no longer exists.
*
* @author Derek Hulley
*/
public class StoreExistsException extends AbstractStoreException
{
private static final long serialVersionUID = 3906369320370975030L;
public StoreExistsException(StoreRef storeRef)
{
super(storeRef);
}
public StoreExistsException(String msg, StoreRef storeRef)
{
super(msg, storeRef);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Reference to a node store
*
* @author Derek Hulley
*/
public final class StoreRef implements EntityRef, Serializable
{
private static final long serialVersionUID = 3905808565129394486L;
public static final String PROTOCOL_WORKSPACE = "workspace";
public static final String URI_FILLER = "://";
private final String protocol;
private final String identifier;
/**
* @param protocol
* well-known protocol for the store, e.g. <b>workspace</b> or
* <b>versionstore</b>
* @param identifier
* the identifier, which may be specific to the protocol
*/
public StoreRef(String protocol, String identifier)
{
if (protocol == null)
{
throw new IllegalArgumentException("Store protocol may not be null");
}
if (identifier == null)
{
throw new IllegalArgumentException("Store identifier may not be null");
}
this.protocol = protocol;
this.identifier = identifier;
}
public StoreRef(String string)
{
int dividerPatternPosition = string.indexOf(URI_FILLER);
if(dividerPatternPosition == -1)
{
throw new AlfrescoRuntimeException("Invalid store ref: Does not contain " + URI_FILLER + " " + string);
}
this.protocol = string.substring(0, dividerPatternPosition);
this.identifier = string.substring(dividerPatternPosition+3);
}
public String toString()
{
return protocol + URI_FILLER + identifier;
}
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj instanceof StoreRef)
{
StoreRef that = (StoreRef) obj;
return (this.protocol.equals(that.protocol)
&& this.identifier.equals(that.identifier));
} else
{
return false;
}
}
/**
* Creates a hashcode from both the {@link #getProtocol()} and {@link #getIdentifier()}
*/
public int hashCode()
{
return (protocol.hashCode() + identifier.hashCode());
}
public String getProtocol()
{
return protocol;
}
public String getIdentifier()
{
return identifier;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* @author Kevin Roast
*/
public class TemplateException extends AlfrescoRuntimeException
{
/**
* @param msgId
*/
public TemplateException(String msgId)
{
super(msgId);
}
/**
* @param msgId
* @param cause
*/
public TemplateException(String msgId, Throwable cause)
{
super(msgId, cause);
}
/**
* @param msgId
* @param params
*/
public TemplateException(String msgId, Object[] params)
{
super(msgId, params);
}
/**
* @param msgId
* @param msgParams
* @param cause
*/
public TemplateException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
/**
* Interface contract for the conversion of file name to a fully qualified icon image path for use by
* the templating engine.
*
* Generally this contract will be implemented by classes that have access to say the webserver
* context which can be used to generate an icon image for a specific filename.
*
* @author Kevin Roast
*/
public interface TemplateImageResolver
{
/**
* Resolve the qualified icon image path for the specified filename
*
* @param filename The file name to resolve image path for
* @param small True to resolve to the small 16x16 image, else large 32x32 image
*/
public String resolveImagePathForName(String filename, boolean small);
}

View File

@@ -0,0 +1,614 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.template.NamePathResultsMap;
import org.alfresco.repo.template.XPathResultsMap;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNameMap;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.InputSource;
import freemarker.ext.dom.NodeModel;
/**
* Node class specific for use by Template pages that support Bean objects as part of the model.
* The default template engine FreeMarker can use these objects and they are provided to support it.
* A single method is completely freemarker specific - getXmlNodeModel()
* <p>
* The class exposes Node properties, children as dynamically populated maps and lists.
* <p>
* Various helper methods are provided to access common and useful node variables such
* as the content url and type information.
*
* @author Kevin Roast
*/
public final class TemplateNode implements Serializable
{
private static final long serialVersionUID = 1234390333739034171L;
private static Log logger = LogFactory.getLog(TemplateNode.class);
private final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN;
private final static String CONTENT_DEFAULT_URL = "/download/direct/{0}/{1}/{2}/{3}";
private final static String CONTENT_PROP_URL = "/download/direct/{0}/{1}/{2}/{3}?property={4}";
/** The children of this node */
private List<TemplateNode> children = null;
/** The associations from this node */
private Map<String, List<TemplateNode>> assocs = null;
/** Cached values */
private NodeRef nodeRef;
private String name;
private QName type;
private String path;
private String id;
private Set<QName> aspects = null;
private QNameMap<String, Object> properties;
private boolean propsRetrieved = false;
private ServiceRegistry services = null;
private Boolean isDocument = null;
private Boolean isContainer = null;
private String displayPath = null;
private String mimetype = null;
private Long size = null;
private TemplateImageResolver imageResolver = null;
private TemplateNode parent = null;
/**
* Constructor
*
* @param nodeRef The NodeRef this Node wrapper represents
* @param services The ServiceRegistry the TemplateNode can use to access services
* @param resolver Image resolver to use to retrieve icons
*/
public TemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver)
{
if (nodeRef == null)
{
throw new IllegalArgumentException("NodeRef must be supplied.");
}
if (services == null)
{
throw new IllegalArgumentException("The ServiceRegistry must be supplied.");
}
this.nodeRef = nodeRef;
this.id = nodeRef.getId();
this.services = services;
this.imageResolver = resolver;
this.properties = new QNameMap<String, Object>(this.services.getNamespaceService());
}
/**
* @return The GUID for the node
*/
public String getId()
{
return this.id;
}
/**
* @return Returns the NodeRef this Node object represents
*/
public NodeRef getNodeRef()
{
return this.nodeRef;
}
/**
* @return Returns the type.
*/
public QName getType()
{
if (this.type == null)
{
this.type = this.services.getNodeService().getType(this.nodeRef);
}
return type;
}
/**
* @return The display name for the node
*/
public String getName()
{
if (this.name == null)
{
// try and get the name from the properties first
this.name = (String)getProperties().get("cm:name");
// if we didn't find it as a property get the name from the association name
if (this.name == null)
{
ChildAssociationRef parentRef = this.services.getNodeService().getPrimaryParent(this.nodeRef);
if (parentRef != null && parentRef.getQName() != null)
{
this.name = parentRef.getQName().getLocalName();
}
else
{
this.name = "";
}
}
}
return this.name;
}
/**
* @return The children of this Node as TemplateNode wrappers
*/
public List<TemplateNode> getChildren()
{
if (this.children == null)
{
List<ChildAssociationRef> childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef);
this.children = new ArrayList<TemplateNode>(childRefs.size());
for (ChildAssociationRef ref : childRefs)
{
// create our Node representation from the NodeRef
TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver);
this.children.add(child);
}
}
return this.children;
}
/**
* @return A map capable of returning the TemplateNode at the specified Path as a child of this node.
*/
public Map getChildByNamePath()
{
return new NamePathResultsMap(this, this.services);
}
/**
* @return A map capable of returning a List of TemplateNode objects from an XPath query
* as children of this node.
*/
public Map getChildrenByXPath()
{
return new XPathResultsMap(this, this.services);
}
/**
* @return The associations for this Node. As a Map of assoc name to a List of TemplateNodes.
*/
public Map<String, List<TemplateNode>> getAssocs()
{
if (this.assocs == null)
{
List<AssociationRef> refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL);
this.assocs = new QNameMap<String, List<TemplateNode>>(this.services.getNamespaceService());
for (AssociationRef ref : refs)
{
String qname = ref.getTypeQName().toString();
List<TemplateNode> nodes = assocs.get(qname);
if (nodes == null)
{
// first access for the list for this qname
nodes = new ArrayList<TemplateNode>(4);
this.assocs.put(ref.getTypeQName().toString(), nodes);
}
nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) );
}
}
return this.assocs;
}
/**
* @return All the properties known about this node.
*/
public Map<String, Object> getProperties()
{
if (this.propsRetrieved == false)
{
Map<QName, Serializable> props = this.services.getNodeService().getProperties(this.nodeRef);
for (QName qname : props.keySet())
{
Serializable propValue = props.get(qname);
if (propValue instanceof NodeRef)
{
// NodeRef object properties are converted to new TemplateNode objects
// so they can be used as objects within a template
propValue = new TemplateNode(((NodeRef)propValue), this.services, this.imageResolver);
}
else if (propValue instanceof ContentData)
{
// ContentData object properties are converted to TemplateContentData objects
// so the content and other properties of those objects can be accessed
propValue = new TemplateContentData((ContentData)propValue, qname);
}
this.properties.put(qname.toString(), propValue);
}
this.propsRetrieved = true;
}
return this.properties;
}
/**
* @return true if this Node is a container (i.e. a folder)
*/
public boolean getIsContainer()
{
if (isContainer == null)
{
DictionaryService dd = this.services.getDictionaryService();
isContainer = Boolean.valueOf( (dd.isSubClass(getType(), ContentModel.TYPE_FOLDER) == true &&
dd.isSubClass(getType(), ContentModel.TYPE_SYSTEM_FOLDER) == false) );
}
return isContainer.booleanValue();
}
/**
* @return true if this Node is a Document (i.e. with content)
*/
public boolean getIsDocument()
{
if (isDocument == null)
{
DictionaryService dd = this.services.getDictionaryService();
isDocument = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CONTENT));
}
return isDocument.booleanValue();
}
/**
* @return The list of aspects applied to this node
*/
public Set<QName> getAspects()
{
if (this.aspects == null)
{
this.aspects = this.services.getNodeService().getAspects(this.nodeRef);
}
return this.aspects;
}
/**
* @param aspect The aspect name to test for
*
* @return true if the node has the aspect false otherwise
*/
public boolean hasAspect(String aspect)
{
if (this.aspects == null)
{
this.aspects = this.services.getNodeService().getAspects(this.nodeRef);
}
if (aspect.startsWith(NAMESPACE_BEGIN))
{
return aspects.contains((QName.createQName(aspect)));
}
else
{
boolean found = false;
for (QName qname : this.aspects)
{
if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect))
{
found = true;
break;
}
}
return found;
}
}
/**
* @return FreeMarker NodeModel for the XML content of this node, or null if no parsable XML found
*/
public NodeModel getXmlNodeModel()
{
try
{
return NodeModel.parse(new InputSource(new StringReader(getContent())));
}
catch (Throwable err)
{
if (logger.isDebugEnabled())
logger.debug(err.getMessage(), err);
return null;
}
}
/**
* @return Display path to this node
*/
public String getDisplayPath()
{
if (displayPath == null)
{
try
{
displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService());
}
catch (AccessDeniedException err)
{
displayPath = "";
}
}
return displayPath;
}
/**
* @return the small icon image for this node
*/
public String getIcon16()
{
if (this.imageResolver != null)
{
if (getIsDocument())
{
return this.imageResolver.resolveImagePathForName(getName(), true);
}
else
{
return "/images/icons/space_small.gif";
}
}
else
{
return "/images/filetypes/_default.gif";
}
}
/**
* @return the large icon image for this node
*/
public String getIcon32()
{
if (this.imageResolver != null)
{
if (getIsDocument())
{
return this.imageResolver.resolveImagePathForName(getName(), false);
}
else
{
String icon = (String)getProperties().get("app:icon");
if (icon != null)
{
return "/images/icons/" + icon + ".gif";
}
else
{
return "/images/icons/space-icon-default.gif";
}
}
}
else
{
return "/images/filetypes32/_default.gif";
}
}
/**
* @return true if the node is currently locked
*/
public boolean getIsLocked()
{
boolean locked = false;
if (getAspects().contains(ContentModel.ASPECT_LOCKABLE))
{
LockStatus lockStatus = this.services.getLockService().getLockStatus(this.nodeRef);
if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
{
locked = true;
}
}
return locked;
}
/**
* @return the parent node
*/
public TemplateNode getParent()
{
if (parent == null)
{
NodeRef parentRef = this.services.getNodeService().getPrimaryParent(nodeRef).getParentRef();
// handle root node (no parent!)
if (parentRef != null)
{
parent = new TemplateNode(parentRef, this.services, this.imageResolver);
}
}
return parent;
}
/**
* @return the content String for this node from the default content property
* (@see ContentModel.PROP_CONTENT)
*/
public String getContent()
{
ContentService contentService = this.services.getContentService();
ContentReader reader = contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
return reader != null ? reader.getContentString() : "";
}
/**
* @return url to the content stream for this node for the default content property
* (@see ContentModel.PROP_CONTENT)
*/
public String getUrl()
{
try
{
return MessageFormat.format(CONTENT_DEFAULT_URL, new Object[] {
nodeRef.getStoreRef().getProtocol(),
nodeRef.getStoreRef().getIdentifier(),
nodeRef.getId(),
URLEncoder.encode(getName(), "US-ASCII") } );
}
catch (UnsupportedEncodingException err)
{
throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err);
}
}
/**
* @return The mimetype encoding for content attached to the node from the default content property
* (@see ContentModel.PROP_CONTENT)
*/
public String getMimetype()
{
if (mimetype == null)
{
TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
mimetype = content.getMimetype();
}
}
return mimetype;
}
/**
* @return The size in bytes of the content attached to the node from the default content property
* (@see ContentModel.PROP_CONTENT)
*/
public long getSize()
{
if (size == null)
{
TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
size = content.getSize();
}
}
return size != null ? size.longValue() : 0L;
}
/**
* @return the image resolver instance used by this node
*/
public TemplateImageResolver getImageResolver()
{
return this.imageResolver;
}
/**
* Override Object.toString() to provide useful debug output
*/
public String toString()
{
if (this.services.getNodeService().exists(nodeRef))
{
return "Node Type: " + getType() +
"\nNode Properties: " + this.getProperties().toString() +
"\nNode Aspects: " + this.getAspects().toString();
}
else
{
return "Node no longer exists: " + nodeRef;
}
}
/**
* Inner class wrapping and providing access to a ContentData property
*/
public class TemplateContentData implements Serializable
{
public TemplateContentData(ContentData contentData, QName property)
{
this.contentData = contentData;
this.property = property;
}
public String getContent()
{
ContentService contentService = services.getContentService();
ContentReader reader = contentService.getReader(nodeRef, property);
return reader != null ? reader.getContentString() : "";
}
public String getUrl()
{
try
{
return MessageFormat.format(CONTENT_PROP_URL, new Object[] {
nodeRef.getStoreRef().getProtocol(),
nodeRef.getStoreRef().getIdentifier(),
nodeRef.getId(),
URLEncoder.encode(getName(), "US-ASCII"),
URLEncoder.encode(property.toString(), "US-ASCII") } );
}
catch (UnsupportedEncodingException err)
{
throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err);
}
}
public long getSize()
{
return contentData.getSize();
}
public String getMimetype()
{
return contentData.getMimetype();
}
private ContentData contentData;
private QName property;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Writer;
/**
* Interface to be implemented by template engine wrapper classes. The developer is responsible
* for interfacing to an appropriate template engine, using the supplied data model as input to
* the template and directing the output to the Writer stream.
*
* @author Kevin Roast
*/
public interface TemplateProcessor
{
/**
* Process a template against the supplied data model and write to the out.
*
* @param template Template name/path
* @param model Object model to process template against
* @param out Writer object to send output too
*/
public void process(String template, Object model, Writer out);
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import java.io.Writer;
/**
* Template Service.
* <p>
* Provides an interface to services for executing template engine against a template file
* and data model.
* <p>
* The service provides a configured list of available template engines. The template file
* can either be in the repository (passed as NodeRef string) or on the classpath. The data
* model is specified to the template engine. The FreeMarker template engine is used by default.
*
* @author Kevin Roast
*/
public interface TemplateService
{
/**
* Process a template against the supplied data model and write to the out.
*
* @param engine Name of the template engine to use
* @param template Template (qualified classpath name or noderef)
* @param model Object model to process template against
*
* @return output of the template process as a String
*/
public String processTemplate(String engine, String template, Object model)
throws TemplateException;
/**
* Process a template against the supplied data model and write to the out.
*
* @param engine Name of the template engine to use
* @param template Template (qualified classpath name or noderef)
* @param model Object model to process template against
* @param out Writer object to send output too
*/
public void processTemplate(String engine, String template, Object model, Writer out)
throws TemplateException;
/**
* Return a TemplateProcessor instance for the specified engine name.
* Note that the processor instance is NOT thread safe!
*
* @param engine Name of the template engine to get or null for default
*
* @return TemplateProcessor
*/
public TemplateProcessor getTemplateProcessor(String engine);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository;
import org.alfresco.error.AlfrescoRuntimeException;
public class XPathException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = 3544955454552815923L;
public XPathException(String msg)
{
super(msg);
}
public XPathException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,705 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository.datatype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO8601DateFormat;
/**
* Support for generic conversion between types.
*
* Additional conversions may be added. Basic interoperabikitynos supported.
*
* Direct conversion and two stage conversions via Number are supported. We do
* not support conversion by any route at the moment
*
* TODO: Add support for Path
*
* TODO: Add support for lucene
*
* TODO: Add suport to check of a type is convertable
*
* TODO: Support for dynamically managing conversions
*
* @author andyh
*
*/
public class DefaultTypeConverter
{
/**
* Default Type Converter
*/
public static TypeConverter INSTANCE = new TypeConverter();
/**
* Initialise default set of Converters
*/
static
{
//
// From string
//
INSTANCE.addConverter(String.class, Boolean.class, new TypeConverter.Converter<String, Boolean>()
{
public Boolean convert(String source)
{
return Boolean.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Character.class, new TypeConverter.Converter<String, Character>()
{
public Character convert(String source)
{
if ((source == null) || (source.length() == 0))
{
return null;
}
return Character.valueOf(source.charAt(0));
}
});
INSTANCE.addConverter(String.class, Number.class, new TypeConverter.Converter<String, Number>()
{
public Number convert(String source)
{
try
{
return DecimalFormat.getNumberInstance().parse(source);
}
catch (ParseException e)
{
throw new TypeConversionException("Failed to parse number " + source, e);
}
}
});
INSTANCE.addConverter(String.class, Byte.class, new TypeConverter.Converter<String, Byte>()
{
public Byte convert(String source)
{
return Byte.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Short.class, new TypeConverter.Converter<String, Short>()
{
public Short convert(String source)
{
return Short.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Integer.class, new TypeConverter.Converter<String, Integer>()
{
public Integer convert(String source)
{
return Integer.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Long.class, new TypeConverter.Converter<String, Long>()
{
public Long convert(String source)
{
return Long.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Float.class, new TypeConverter.Converter<String, Float>()
{
public Float convert(String source)
{
return Float.valueOf(source);
}
});
INSTANCE.addConverter(String.class, Double.class, new TypeConverter.Converter<String, Double>()
{
public Double convert(String source)
{
return Double.valueOf(source);
}
});
INSTANCE.addConverter(String.class, BigInteger.class, new TypeConverter.Converter<String, BigInteger>()
{
public BigInteger convert(String source)
{
return new BigInteger(source);
}
});
INSTANCE.addConverter(String.class, BigDecimal.class, new TypeConverter.Converter<String, BigDecimal>()
{
public BigDecimal convert(String source)
{
return new BigDecimal(source);
}
});
INSTANCE.addConverter(String.class, Date.class, new TypeConverter.Converter<String, Date>()
{
public Date convert(String source)
{
Date date = ISO8601DateFormat.parse(source);
if (date == null)
{
throw new TypeConversionException("Failed to parse date " + source);
}
return date;
}
});
INSTANCE.addConverter(String.class, Duration.class, new TypeConverter.Converter<String, Duration>()
{
public Duration convert(String source)
{
return new Duration(source);
}
});
INSTANCE.addConverter(String.class, QName.class, new TypeConverter.Converter<String, QName>()
{
public QName convert(String source)
{
return QName.createQName(source);
}
});
INSTANCE.addConverter(String.class, ContentData.class, new TypeConverter.Converter<String, ContentData>()
{
public ContentData convert(String source)
{
return ContentData.createContentProperty(source);
}
});
INSTANCE.addConverter(String.class, NodeRef.class, new TypeConverter.Converter<String, NodeRef>()
{
public NodeRef convert(String source)
{
return new NodeRef(source);
}
});
INSTANCE.addConverter(String.class, InputStream.class, new TypeConverter.Converter<String, InputStream>()
{
public InputStream convert(String source)
{
try
{
return new ByteArrayInputStream(source.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e)
{
throw new TypeConversionException("Encoding not supported", e);
}
}
});
//
// Number to Subtypes and Date
//
INSTANCE.addConverter(Number.class, Byte.class, new TypeConverter.Converter<Number, Byte>()
{
public Byte convert(Number source)
{
return Byte.valueOf(source.byteValue());
}
});
INSTANCE.addConverter(Number.class, Short.class, new TypeConverter.Converter<Number, Short>()
{
public Short convert(Number source)
{
return Short.valueOf(source.shortValue());
}
});
INSTANCE.addConverter(Number.class, Integer.class, new TypeConverter.Converter<Number, Integer>()
{
public Integer convert(Number source)
{
return Integer.valueOf(source.intValue());
}
});
INSTANCE.addConverter(Number.class, Long.class, new TypeConverter.Converter<Number, Long>()
{
public Long convert(Number source)
{
return Long.valueOf(source.longValue());
}
});
INSTANCE.addConverter(Number.class, Float.class, new TypeConverter.Converter<Number, Float>()
{
public Float convert(Number source)
{
return Float.valueOf(source.floatValue());
}
});
INSTANCE.addConverter(Number.class, Double.class, new TypeConverter.Converter<Number, Double>()
{
public Double convert(Number source)
{
return Double.valueOf(source.doubleValue());
}
});
INSTANCE.addConverter(Number.class, Date.class, new TypeConverter.Converter<Number, Date>()
{
public Date convert(Number source)
{
return new Date(source.longValue());
}
});
INSTANCE.addConverter(Number.class, String.class, new TypeConverter.Converter<Number, String>()
{
public String convert(Number source)
{
return source.toString();
}
});
INSTANCE.addConverter(Number.class, BigInteger.class, new TypeConverter.Converter<Number, BigInteger>()
{
public BigInteger convert(Number source)
{
if (source instanceof BigDecimal)
{
return ((BigDecimal) source).toBigInteger();
}
else
{
return BigInteger.valueOf(source.longValue());
}
}
});
INSTANCE.addConverter(Number.class, BigDecimal.class, new TypeConverter.Converter<Number, BigDecimal>()
{
public BigDecimal convert(Number source)
{
if (source instanceof BigInteger)
{
return new BigDecimal((BigInteger) source);
}
else
{
return BigDecimal.valueOf(source.longValue());
}
}
});
INSTANCE.addDynamicTwoStageConverter(Number.class, String.class, InputStream.class);
//
// Date, Timestamp ->
//
INSTANCE.addConverter(Timestamp.class, Date.class, new TypeConverter.Converter<Timestamp, Date>()
{
public Date convert(Timestamp source)
{
return new Date(source.getTime());
}
});
INSTANCE.addConverter(Date.class, Number.class, new TypeConverter.Converter<Date, Number>()
{
public Number convert(Date source)
{
return Long.valueOf(source.getTime());
}
});
INSTANCE.addConverter(Date.class, String.class, new TypeConverter.Converter<Date, String>()
{
public String convert(Date source)
{
return ISO8601DateFormat.format(source);
}
});
INSTANCE.addConverter(Date.class, Calendar.class, new TypeConverter.Converter<Date, Calendar>()
{
public Calendar convert(Date source)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(source);
return calendar;
}
});
INSTANCE.addDynamicTwoStageConverter(Date.class, String.class, InputStream.class);
//
// Boolean ->
//
INSTANCE.addConverter(Boolean.class, String.class, new TypeConverter.Converter<Boolean, String>()
{
public String convert(Boolean source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Boolean.class, String.class, InputStream.class);
//
// Character ->
//
INSTANCE.addConverter(Character.class, String.class, new TypeConverter.Converter<Character, String>()
{
public String convert(Character source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Character.class, String.class, InputStream.class);
//
// Duration ->
//
INSTANCE.addConverter(Duration.class, String.class, new TypeConverter.Converter<Duration, String>()
{
public String convert(Duration source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Duration.class, String.class, InputStream.class);
//
// Byte
//
INSTANCE.addConverter(Byte.class, String.class, new TypeConverter.Converter<Byte, String>()
{
public String convert(Byte source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Byte.class, String.class, InputStream.class);
//
// Short
//
INSTANCE.addConverter(Short.class, String.class, new TypeConverter.Converter<Short, String>()
{
public String convert(Short source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Short.class, String.class, InputStream.class);
//
// Integer
//
INSTANCE.addConverter(Integer.class, String.class, new TypeConverter.Converter<Integer, String>()
{
public String convert(Integer source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Integer.class, String.class, InputStream.class);
//
// Long
//
INSTANCE.addConverter(Long.class, String.class, new TypeConverter.Converter<Long, String>()
{
public String convert(Long source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Long.class, String.class, InputStream.class);
//
// Float
//
INSTANCE.addConverter(Float.class, String.class, new TypeConverter.Converter<Float, String>()
{
public String convert(Float source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Float.class, String.class, InputStream.class);
//
// Double
//
INSTANCE.addConverter(Double.class, String.class, new TypeConverter.Converter<Double, String>()
{
public String convert(Double source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Double.class, String.class, InputStream.class);
//
// BigInteger
//
INSTANCE.addConverter(BigInteger.class, String.class, new TypeConverter.Converter<BigInteger, String>()
{
public String convert(BigInteger source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(BigInteger.class, String.class, InputStream.class);
//
// Calendar
//
INSTANCE.addConverter(Calendar.class, Date.class, new TypeConverter.Converter<Calendar, Date>()
{
public Date convert(Calendar source)
{
return source.getTime();
}
});
INSTANCE.addConverter(Calendar.class, String.class, new TypeConverter.Converter<Calendar, String>()
{
public String convert(Calendar source)
{
return ISO8601DateFormat.format(source.getTime());
}
});
//
// BigDecimal
//
INSTANCE.addConverter(BigDecimal.class, String.class, new TypeConverter.Converter<BigDecimal, String>()
{
public String convert(BigDecimal source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(BigDecimal.class, String.class, InputStream.class);
//
// QName
//
INSTANCE.addConverter(QName.class, String.class, new TypeConverter.Converter<QName, String>()
{
public String convert(QName source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(QName.class, String.class, InputStream.class);
//
// NodeRef
//
INSTANCE.addConverter(NodeRef.class, String.class, new TypeConverter.Converter<NodeRef, String>()
{
public String convert(NodeRef source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(NodeRef.class, String.class, InputStream.class);
//
// ContentData
//
INSTANCE.addConverter(ContentData.class, String.class, new TypeConverter.Converter<ContentData, String>()
{
public String convert(ContentData source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(ContentData.class, String.class, InputStream.class);
//
// Path
//
INSTANCE.addConverter(Path.class, String.class, new TypeConverter.Converter<Path, String>()
{
public String convert(Path source)
{
return source.toString();
}
});
INSTANCE.addDynamicTwoStageConverter(Path.class, String.class, InputStream.class);
//
// Content Reader
//
INSTANCE.addConverter(ContentReader.class, InputStream.class, new TypeConverter.Converter<ContentReader, InputStream>()
{
public InputStream convert(ContentReader source)
{
return source.getContentInputStream();
}
});
INSTANCE.addConverter(ContentReader.class, String.class, new TypeConverter.Converter<ContentReader, String>()
{
public String convert(ContentReader source)
{
String encoding = source.getEncoding();
if (encoding == null || !encoding.equals("UTF-8"))
{
throw new TypeConversionException("Cannot convert non UTF-8 streams to String.");
}
// TODO: Throw error on size limit
return source.getContentString();
}
});
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, Date.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, Double.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, Long.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, Boolean.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, QName.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, Path.class);
INSTANCE.addDynamicTwoStageConverter(ContentReader.class, String.class, NodeRef.class);
//
// Input Stream
//
INSTANCE.addConverter(InputStream.class, String.class, new TypeConverter.Converter<InputStream, String>()
{
public String convert(InputStream source)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int read;
while ((read = source.read(buffer)) > 0)
{
out.write(buffer, 0, read);
}
byte[] data = out.toByteArray();
return new String(data, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
throw new TypeConversionException("Cannot convert input stream to String.", e);
}
catch (IOException e)
{
throw new TypeConversionException("Conversion from stream to string failed", e);
}
finally
{
if (source != null)
{
try { source.close(); } catch(IOException e) {};
}
}
}
});
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, Date.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, Double.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, Long.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, Boolean.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, QName.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, Path.class);
INSTANCE.addDynamicTwoStageConverter(InputStream.class, String.class, NodeRef.class);
}
}

View File

@@ -0,0 +1,282 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository.datatype;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import junit.framework.TestCase;
import org.alfresco.util.ISO8601DateFormat;
public class DefaultTypeConverterTest extends TestCase
{
public DefaultTypeConverterTest()
{
super();
}
public DefaultTypeConverterTest(String arg0)
{
super(arg0);
}
public void testPrimitives()
{
assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, false));
assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, true));
assertEquals(Character.valueOf('a'), DefaultTypeConverter.INSTANCE.convert(Character.class, 'a'));
assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, (byte) 3));
assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, (short) 4));
assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, (int) 5));
assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, (long) 6));
assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, (float) 7.1));
assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, (double) 123.123));
}
public void testNoConversion()
{
assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, Boolean.valueOf(false)));
assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, Boolean.valueOf(true)));
assertEquals(Character.valueOf('w'), DefaultTypeConverter.INSTANCE.convert(Character.class, Character.valueOf('w')));
assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Byte.valueOf("3")));
assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, Short.valueOf("4")));
assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Integer.valueOf("5")));
assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, Long.valueOf("6")));
assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, Float.valueOf("7.1")));
assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("123.123")));
assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("123.123")));
assertEquals(new BigInteger("1234567890123456789"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigInteger("1234567890123456789")));
assertEquals(new BigDecimal("12345678901234567890.12345678901234567890"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigDecimal("12345678901234567890.12345678901234567890")));
Date date = new Date();
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, date));
assertEquals(new Duration("P25D"), DefaultTypeConverter.INSTANCE.convert(Duration.class, new Duration("P25D")));
assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof"));
}
public void testToString()
{
assertEquals("true", DefaultTypeConverter.INSTANCE.convert(String.class, new Boolean(true)));
assertEquals("false", DefaultTypeConverter.INSTANCE.convert(String.class, new Boolean(false)));
assertEquals("v", DefaultTypeConverter.INSTANCE.convert(String.class, Character.valueOf('v')));
assertEquals("3", DefaultTypeConverter.INSTANCE.convert(String.class, Byte.valueOf("3")));
assertEquals("4", DefaultTypeConverter.INSTANCE.convert(String.class, Short.valueOf("4")));
assertEquals("5", DefaultTypeConverter.INSTANCE.convert(String.class, Integer.valueOf("5")));
assertEquals("6", DefaultTypeConverter.INSTANCE.convert(String.class, Long.valueOf("6")));
assertEquals("7.1", DefaultTypeConverter.INSTANCE.convert(String.class, Float.valueOf("7.1")));
assertEquals("123.123", DefaultTypeConverter.INSTANCE.convert(String.class, Double.valueOf("123.123")));
assertEquals("1234567890123456789", DefaultTypeConverter.INSTANCE.convert(String.class, new BigInteger("1234567890123456789")));
assertEquals("12345678901234567890.12345678901234567890", DefaultTypeConverter.INSTANCE.convert(String.class, new BigDecimal("12345678901234567890.12345678901234567890")));
Date date = new Date();
assertEquals(ISO8601DateFormat.format(date), DefaultTypeConverter.INSTANCE.convert(String.class, date));
assertEquals("P0Y25D", DefaultTypeConverter.INSTANCE.convert(String.class, new Duration("P0Y25D")));
assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof"));
}
public void testFromString()
{
assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, "True"));
assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, "woof"));
assertEquals(Character.valueOf('w'), DefaultTypeConverter.INSTANCE.convert(Character.class, "w"));
assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, "3"));
assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, "4"));
assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, "5"));
assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, "6"));
assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, "7.1"));
assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, "123.123"));
assertEquals(new BigInteger("1234567890123456789"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, "1234567890123456789"));
assertEquals(new BigDecimal("12345678901234567890.12345678901234567890"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, "12345678901234567890.12345678901234567890"));
assertEquals("2004-03-12T00:00:00.000Z", ISO8601DateFormat.format(DefaultTypeConverter.INSTANCE.convert(Date.class, "2004-03-12T00:00:00.000Z")));
assertEquals(new Duration("P25D"), DefaultTypeConverter.INSTANCE.convert(Duration.class, "P25D"));
assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof"));
}
public void testPrimativeAccessors()
{
assertEquals(false, DefaultTypeConverter.INSTANCE.convert(Boolean.class, false).booleanValue());
assertEquals(true, DefaultTypeConverter.INSTANCE.convert(Boolean.class, true).booleanValue());
assertEquals('a', DefaultTypeConverter.INSTANCE.convert(Character.class, 'a').charValue());
assertEquals((byte) 3, DefaultTypeConverter.INSTANCE.convert(Byte.class, (byte) 3).byteValue());
assertEquals((short) 4, DefaultTypeConverter.INSTANCE.convert(Short.class, (short) 4).shortValue());
assertEquals((int) 5, DefaultTypeConverter.INSTANCE.convert(Integer.class, (int) 5).intValue());
assertEquals((long) 6, DefaultTypeConverter.INSTANCE.convert(Long.class, (long) 6).longValue());
assertEquals((float) 7.1, DefaultTypeConverter.INSTANCE.convert(Float.class, (float) 7.1).floatValue());
assertEquals((double) 123.123, DefaultTypeConverter.INSTANCE.convert(Double.class, (double) 123.123).doubleValue());
}
public void testInterConversions()
{
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Byte.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Byte.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Byte.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Byte.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Byte.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Byte.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Byte.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Byte.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Short.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Short.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Short.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Short.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Short.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Short.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Short.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Short.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Integer.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Integer.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Integer.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Integer.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Integer.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Integer.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Integer.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Integer.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Long.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Long.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Long.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Long.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Long.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Long.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Long.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Long.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Float.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Float.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Float.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Float.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Float.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Float.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Float.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Float.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Double.valueOf("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Double.valueOf("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Double.valueOf("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Double.valueOf("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Double.valueOf("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Double.valueOf("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Double.valueOf("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, new BigInteger("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, new BigInteger("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, new BigInteger("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, new BigInteger("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, new BigInteger("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, new BigInteger("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigInteger("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigInteger("8")));
assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, new BigDecimal("1")));
assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, new BigDecimal("2")));
assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, new BigDecimal("3")));
assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, new BigDecimal("4")));
assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, new BigDecimal("5")));
assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, new BigDecimal("6")));
assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigDecimal("7")));
assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigDecimal("8")));
}
public void testDate()
{
Date date = new Date(101);
assertEquals(Byte.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Byte.class, date));
assertEquals(Short.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Short.class, date));
assertEquals(Integer.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Integer.class, date));
assertEquals(Long.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Long.class, date));
assertEquals(Float.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Float.class, date));
assertEquals(Double.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Double.class, date));
assertEquals(new BigInteger("101"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, date));
assertEquals(new BigDecimal("101"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, date));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (byte)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (short)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (int)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (long)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (float)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (double)101));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, new BigInteger("101")));
assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (Object)(new BigDecimal("101"))));
assertEquals(101, DefaultTypeConverter.INSTANCE.intValue(date));
}
public void testMultiValue()
{
ArrayList<Object> list = makeList();
assertEquals(true, DefaultTypeConverter.INSTANCE.isMultiValued(list));
assertEquals(14, DefaultTypeConverter.INSTANCE.size(list));
for(String stringValue: DefaultTypeConverter.INSTANCE.getCollection(String.class, list))
{
System.out.println("Value is "+stringValue);
}
}
private ArrayList<Object> makeList()
{
ArrayList<Object> list = new ArrayList<Object>();
list.add(Boolean.valueOf(true));
list.add(Boolean.valueOf(false));
list.add(Character.valueOf('q'));
list.add(Byte.valueOf("1"));
list.add(Short.valueOf("2"));
list.add(Integer.valueOf("3"));
list.add(Long.valueOf("4"));
list.add(Float.valueOf("5"));
list.add(Double.valueOf("6"));
list.add(new BigInteger("7"));
list.add(new BigDecimal("8"));
list.add(new Date());
list.add(new Duration("P5Y0M"));
list.add("Hello mum");
return list;
}
public void testSingleValuseAsMultiValue()
{
Integer integer = Integer.valueOf(43);
assertEquals(false, DefaultTypeConverter.INSTANCE.isMultiValued(integer));
assertEquals(1, DefaultTypeConverter.INSTANCE.size(integer));
for(String stringValue: DefaultTypeConverter.INSTANCE.getCollection(String.class, integer))
{
System.out.println("Value is "+stringValue);
}
}
public void testNullAndEmpty()
{
assertNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, null));
ArrayList<Object> list = new ArrayList<Object>();
assertNotNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, list));
list.add(null);
assertNotNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, list));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository.datatype;
/**
* Base Exception of Type Converter Exceptions.
*
* @author David Caruana
*/
public class TypeConversionException extends RuntimeException
{
private static final long serialVersionUID = 3257008761007847733L;
public TypeConversionException(String msg)
{
super(msg);
}
public TypeConversionException(String msg, Throwable cause)
{
super(msg, cause);
}
}

View File

@@ -0,0 +1,596 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.repository.datatype;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.util.ParameterCheck;
/**
* Support for generic conversion between types.
*
* Additional conversions may be added.
*
* Direct conversion and two stage conversions via Number are supported. We do
* not support conversion by any route at the moment
*/
public class TypeConverter
{
/**
* General conversion method to Object types (note it cannot support
* conversion to primary types due the restrictions of reflection. Use the
* static conversion methods to primitive types)
*
* @param propertyType - the target property type
* @param value - the value to be converted
* @return - the converted value as the correct type
*/
@SuppressWarnings("unchecked")
public final Object convert(DataTypeDefinition propertyType, Object value)
{
ParameterCheck.mandatory("Property type definition", propertyType);
// Convert property type to java class
Class javaClass = null;
String javaClassName = propertyType.getJavaClassName();
try
{
javaClass = Class.forName(javaClassName);
}
catch (ClassNotFoundException e)
{
throw new DictionaryException("Java class " + javaClassName + " of property type " + propertyType.getName() + " is invalid", e);
}
return convert(javaClass, value);
}
/**
* General conversion method to Object types (note it cannot support
* conversion to primary types due the restrictions of reflection. Use the
* static conversion methods to primitive types)
*
* @param <T> The target type for the result of the conversion
* @param c - a class for the target type
* @param value - the value to be converted
* @return - the converted value as the correct type
* @throws TypeConversionException if the conversion cannot be performed
*/
@SuppressWarnings("unchecked")
public final <T> T convert(Class<T> c, Object value)
{
if(value == null)
{
return null;
}
// Primative types
if (c.isPrimitive())
{
// We can not suport primitive type conversion
throw new TypeConversionException("Can not convert direct to primitive type " + c.getName());
}
// Check if we already have the correct type
if (c.isInstance(value))
{
return c.cast(value);
}
// Find the correct conversion - if available and do the converiosn
Converter converter = getConverter(value, c);
if (converter == null)
{
throw new TypeConversionException(
"There is no conversion registered for the value: \n" +
" value class: " + value.getClass().getName() + "\n" +
" to class: " + c.getName() + "\n" +
" value: " + value.toString());
}
return (T) converter.convert(value);
}
/**
* General conversion method to convert collection contents to the specified
* type.
*
* @param propertyType - the target property type
* @param value - the value to be converted
* @return - the converted value as the correct type
* @throws DictionaryException if the property type's registered java class is invalid
* @throws TypeConversionException if the conversion cannot be performed
*/
@SuppressWarnings("unchecked")
public final Collection convert(DataTypeDefinition propertyType, Collection values)
{
ParameterCheck.mandatory("Property type definition", propertyType);
// Convert property type to java class
Class javaClass = null;
String javaClassName = propertyType.getJavaClassName();
try
{
javaClass = Class.forName(javaClassName);
}
catch (ClassNotFoundException e)
{
throw new DictionaryException("Java class " + javaClassName + " of property type " + propertyType.getName() + " is invalid", e);
}
return convert(javaClass, values);
}
/**
* General conversion method to convert collection contents to the specified
* type.
*
* @param <T> The target type for the result of the conversion
* @param c - a class for the target type
* @param value - the collection to be converted
* @return - the converted collection
* @throws TypeConversionException if the conversion cannot be performed
*/
public final <T> Collection<T> convert(Class<T> c, Collection values)
{
if(values == null)
{
return null;
}
Collection<T> converted = new ArrayList<T>(values.size());
for (Object value : values)
{
converted.add(convert(c, value));
}
return converted;
}
/**
* Get the boolean value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final boolean booleanValue(Object value)
{
return convert(Boolean.class, value).booleanValue();
}
/**
* Get the char value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final char charValue(Object value)
{
return convert(Character.class, value).charValue();
}
/**
* Get the byte value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final byte byteValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).byteValue();
}
return convert(Byte.class, value).byteValue();
}
/**
* Get the short value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final short shortValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).shortValue();
}
return convert(Short.class, value).shortValue();
}
/**
* Get the int value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final int intValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).intValue();
}
return convert(Integer.class, value).intValue();
}
/**
* Get the long value for the value object
* May have conversion failure
*
* @param value
* @return
*/
public final long longValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).longValue();
}
return convert(Long.class, value).longValue();
}
/**
* Get the bollean value for the value object
* May have conversion failure
*
* @param float
* @return
*/
public final float floatValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).floatValue();
}
return convert(Float.class, value).floatValue();
}
/**
* Get the bollean value for the value object
* May have conversion failure
*
* @param double
* @return
*/
public final double doubleValue(Object value)
{
if (value instanceof Number)
{
return ((Number) value).doubleValue();
}
return convert(Double.class, value).doubleValue();
}
/**
* Is the value multi valued
*
* @param value
* @return true - if the underlyinf is a collection of values and not a singole value
*/
public final boolean isMultiValued(Object value)
{
return (value instanceof Collection);
}
/**
* Get the number of values represented
*
* @param value
* @return 1 for normal values and the size of the collection for MVPs
*/
public final int size(Object value)
{
if (value instanceof Collection)
{
return ((Collection) value).size();
}
else
{
return 1;
}
}
/**
* Get a collection for the passed value
*
* @param value
* @return
*/
private final Collection createCollection(Object value)
{
Collection coll;
if (isMultiValued(value))
{
coll = (Collection) value;
}
else
{
ArrayList<Object> list = new ArrayList<Object>(1);
list.add(value);
coll = list;
}
return coll;
}
/**
* Get a collection for the passed value converted to the specified type
*
* @param c
* @param value
* @return
*/
public final <T> Collection<T> getCollection(Class<T> c, Object value)
{
Collection coll = createCollection(value);
return convert(c, coll);
}
/**
* Add a converter to the list of those available
*
* @param <F>
* @param <T>
* @param source
* @param destination
* @param converter
*/
public final <F, T> void addConverter(Class<F> source, Class<T> destination, Converter<F, T> converter)
{
Map<Class, Converter> map = conversions.get(source);
if (map == null)
{
map = new HashMap<Class, Converter>();
conversions.put(source, map);
}
map.put(destination, converter);
}
/**
* Add a dynamic two stage converter
* @param <F> from
* @param <I> intermediate
* @param <T> to
* @param source
* @param intermediate
* @param destination
*/
public final <F, I, T> Converter<F, T> addDynamicTwoStageConverter(Class<F> source, Class<I> intermediate, Class<T> destination)
{
Converter<F, T> converter = new TypeConverter.DynamicTwoStageConverter<F, I, T>(source, intermediate, destination);
addConverter(source, destination, converter);
return converter;
}
/**
* Find conversion for the specified object
*
* Note: Takes into account the class of the object and any interfaces it may
* also support.
*
* @param <F>
* @param <T>
* @param source
* @param dest
* @return
*/
@SuppressWarnings("unchecked")
public final <T> Converter getConverter(Object value, Class<T> dest)
{
Converter converter = null;
if (value == null)
{
return null;
}
// find via class of value
Class valueClass = value.getClass();
converter = getConverter(valueClass, dest);
if (converter != null)
{
return converter;
}
// find via supported interfaces of value
do
{
Class[] ifClasses = valueClass.getInterfaces();
for (Class ifClass : ifClasses)
{
converter = getConverter(ifClass, dest);
if (converter != null)
{
return converter;
}
}
valueClass = valueClass.getSuperclass();
}
while (valueClass != null);
return null;
}
/**
* Find a conversion for a specific Class
*
* @param <F>
* @param <T>
* @param source
* @param dest
* @return
*/
public <F, T> Converter getConverter(Class<F> source, Class<T> dest)
{
Converter<?, ?> converter = null;
Class clazz = source;
do
{
Map<Class, Converter> map = conversions.get(clazz);
if (map == null)
{
continue;
}
converter = map.get(dest);
if (converter == null)
{
// attempt to establish converter from source to dest via Number
Converter<?, ?> first = map.get(Number.class);
Converter<?, ?> second = null;
if (first != null)
{
map = conversions.get(Number.class);
if (map != null)
{
second = map.get(dest);
}
}
if (second != null)
{
converter = new TwoStageConverter<F, Number, T>(first, second);
}
}
}
while ((converter == null) && ((clazz = clazz.getSuperclass()) != null));
return converter;
}
/**
* Map of conversion
*/
private Map<Class, Map<Class, Converter>> conversions = new HashMap<Class, Map<Class, Converter>>();
// Support for pluggable conversions
/**
* Conversion interface
*
* @author andyh
*
* @param <F> From type
* @param <T> To type
*/
public interface Converter<F, T>
{
public T convert(F source);
}
/**
* Support for chaining conversions
*
* @author andyh
*
* @param <F> From Type
* @param <I> Intermediate type
* @param <T> To Type
*/
public static class TwoStageConverter<F, I, T> implements Converter<F, T>
{
Converter first;
Converter second;
TwoStageConverter(Converter first, Converter second)
{
this.first = first;
this.second = second;
}
@SuppressWarnings("unchecked")
public T convert(F source)
{
return (T) second.convert((I) first.convert(source));
}
}
/**
* Support for chaining conversions
*
* @author David Caruana
*
* @param <F> From Type
* @param <I> Intermediate type
* @param <T> To Type
*/
protected class DynamicTwoStageConverter<F, I, T> implements Converter<F, T>
{
Class<F> from;
Class<I> intermediate;
Class<T> to;
DynamicTwoStageConverter(Class<F> from, Class<I> intermediate, Class<T> to)
{
this.from = from;
this.intermediate = intermediate;
this.to = to;
}
/**
* @return from class
*/
public Class<F> getFrom()
{
return from;
}
/**
* @return intermediate class
*/
public Class<I> getIntermediate()
{
return intermediate;
}
/**
* @return to class
*/
public Class<T> getTo()
{
return to;
}
@SuppressWarnings("unchecked")
public T convert(F source)
{
Converter iConverter = TypeConverter.this.getConverter(from, intermediate);
Converter tConverter = TypeConverter.this.getConverter(intermediate, to);
if (iConverter == null || tConverter == null)
{
throw new TypeConversionException("Cannot convert from " + from.getName() + " to " + to.getName());
}
Object iValue = iConverter.convert(source);
Object tValue = tConverter.convert(iValue);
return (T)tValue;
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.rule;
import org.alfresco.service.cmr.action.CompositeAction;
/**
* Rule Interface
*
* @author Roy Wetherall
*/
public interface Rule extends CompositeAction
{
/**
* Indicates that the rule is applied to the children of the associated
* node, not just the node itself.
* <p>
* By default this will be set to false.
*
* @return true if the rule is applied to the children of the associated node,
* false otherwise
*/
boolean isAppliedToChildren();
/**
* Set whether the rule is applied to all children of the associated node
* rather than just the node itself.
*
* @param isAppliedToChildren true if the rule should be applied to the children, false
* otherwise
*/
void applyToChildren(boolean isAppliedToChildren);
/**
* Get the rule type name
*
* @return the rule type name
*/
String getRuleTypeName();
}

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.rule;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Rule service interface.
*
* @author Roy Wetherall
*/
public interface RuleService
{
/**
* Get the rule types currently defined in the repository.
*
* @return a list of rule types
*/
public List<RuleType> getRuleTypes();
/**
* Gets a rule type by name.
*
* @param name the name of the rule type
* @return the rule type, null if not found
*/
public RuleType getRuleType(String name);
/**
* Indicates wether the rules for a given node are enabled or not. If the
* rules are not enabled then they will not be executed.
*
* @param nodeRef the node reference
* @return true if the rules are enabled, false otherwise
*/
public boolean rulesEnabled(NodeRef nodeRef);
/**
* Disables the rules for a given node reference. When the rules are disabled they
* will not execute.
*
* @param nodeRef the node reference
*/
public void disableRules(NodeRef nodeRef);
/**
* Enables the rules for a given node reference. When the rules are enabled they
* will execute as usual. By default all rules are enabled.
*
* @param nodeRef the node reference
*/
public void enableRules(NodeRef nodeRef);
/**
* Disables a rule, preventing it from being fired.
*
* @param rule the rule to disable
*/
public void disableRule(Rule rule);
/**
* Enables a rule previously disabled.
*
* @param rule the rule to enable
*/
public void enableRule(Rule rule);
/**
* Indicates whether the node in question has any rules associated with it.
*
* @param nodeRef the node reference
* @return true if the node has rules associated, false otherwise
*/
public boolean hasRules(NodeRef nodeRef);
/**
* Get all the rules associated with an actionable node, including those
* inherited from parents.
* <p>
* An exception is raised if the actionable aspect is not present on the
* passed node.
*
* @param nodeRef the node reference
* @return a list of the rules associated with the node
*/
public List<Rule> getRules(NodeRef nodeRef);
/**
* Get the rules associated with an actionable node.
* <p>
* Optionally this list includes rules inherited from its parents.
* <p>
* An exception is raised if the actionable aspect is not present on the
* passed node.
*
* @param nodeRef the node reference
* @param includeInhertied indicates whether the inherited rules should be included in
* the result list or not
* @return a list of the rules associated with the node
*/
public List<Rule> getRules(NodeRef nodeRef, boolean includeInhertied);
/**
* Get the rules associatied with an actionable node that are of a specific rule type.
*
* @param nodeRef the node reference
* @param includeInhertiedRuleType indicates whether the inherited rules should be included in
* the result list or not
* @param ruleTypeName the name of the rule type, if null is passed all rule types
* are returned
* @return a list of the rules associated with the node
*/
public List<Rule> getRules(NodeRef nodeRef, boolean includeInhertiedRuleType, String ruleTypeName);
/**
* Get the rule given its id.
*
* @param nodeRef the node reference
* @param ruleId the rule id
* @return the rule corresponding ot the id
*/
public Rule getRule(NodeRef nodeRef, String ruleId);
/**
* Helper method to create a new rule.
* <p>
* Call add rule once the details of the rule have been specified in order
* to associate the rule with a node reference.
*
* @param ruleTypeName the name of the rule type
* @return the created rule
*/
public Rule createRule(String ruleTypeName);
/**
* Saves the details of the rule to the specified node reference.
* <p>
* If the rule is already associated with the node, the details are updated
* with those specified.
*
* @param nodeRef
* @param rule
*/
public void saveRule(NodeRef nodeRef, Rule rule);
/**
* Removes a rule from the given rule actionable node
*
* @param nodeRef the actionable node reference
*/
public void removeRule(NodeRef nodeRef, Rule rule);
/**
* Removes all the rules associated with an actionable node
*
* @param nodeRef the actionable node reference
*/
public void removeAllRules(NodeRef nodeRef);
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.rule;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Rule Service Exception Class
*
* @author Roy Wetherall
*/
public class RuleServiceException extends AlfrescoRuntimeException
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 3257571685241467958L;
/**
* Construtor
*
* @param message the message string
*/
public RuleServiceException(String message)
{
super(message);
}
/**
* Constructor
*
* @param message the message string
* @param source the source exception
*/
public RuleServiceException(String message, Throwable source)
{
super(message, source);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.rule;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Rule type interface.
*
* @author Roy Wetherall
*/
public interface RuleType
{
/**
* Some rule type constants
*/
public static final String INBOUND = "inbound";
public static final String OUTGOING = "outgoing";
/**
* Get the name of the rule type.
* <p>
* The name is unique and is used to identify the rule type.
*
* @return the name of the rule type
*/
public String getName();
/**
* Get the display label of the rule type.
*
* @return the display label
*/
public String getDisplayLabel();
/**
* Trigger the rules of the rule type for the node on the actioned upon node.
*
* @param nodeRef the node ref whos rule of rule type are to be triggered
* @param actionedUponNodeRef the node ref that the triggered rule will action upon
*/
public void triggerRuleType(NodeRef nodeRef, NodeRef actionedUponNodeRef);
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.util.Collection;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
/**
* Category Service
*
* The service for querying and creating categories.
* All other management can be carried out using the node service.
*
* Classification - the groupings of categories. There is a one-to-one mapping with aspects. For example, Region.
* Root Category - the top level categories in a classification. For example, Northern Europe
* Category - any other category below a root category
*
* @author Andy Hind
*
*/
public interface CategoryService
{
/**
* Enumeration for navigation control.
*
* MEMBERS - get only category members (the things that have been classified in a category, not the sub categories)
* SUB_CATEGORIES - get sub categories only, not the things that hyave been classified.
* ALL - get both of the above
*/
public enum Mode {MEMBERS, SUB_CATEGORIES, ALL};
/**
* Depth from which to get nodes.
*
* IMMEDIATE - only immediate sub categories or members
* ANY - find subcategories or members at any level
*/
public enum Depth {IMMEDIATE, ANY};
/**
* Get the children of a given category node
*
* @param categoryRef - the category node
* @param mode - the enumeration mode for what to recover
* @param depth - the enumeration depth for what level to recover
* @return a collection of all the nodes found identified by their ChildAssocRef's
*/
public Collection<ChildAssociationRef> getChildren(NodeRef categoryRef, Mode mode, Depth depth );
/**
* Get a list of all the categories appropriate for a given property.
* The full list of categories that may be assigned for this aspect.
*
* @param aspectQName
* @param depth - the enumeration depth for what level to recover
* @return a collection of all the nodes found identified by their ChildAssocRef's
*/
public Collection<ChildAssociationRef> getCategories(StoreRef storeRef, QName aspectQName, Depth depth );
/**
* Get all the classification entries
*
* @return
*/
public Collection<ChildAssociationRef> getClassifications(StoreRef storeRef);
/**
* Get the root categories for an aspect/classification
*
* @param storeRef
* @param aspectName
* @return
*/
public Collection<ChildAssociationRef> getRootCategories(StoreRef storeRef, QName aspectName);
/**
* Get all the types that represent categories
*
* @return
*/
public Collection<QName> getClassificationAspects();
/**
* Create a new category.
*
* This will extend the category types in the data dictionary
* All it needs is the type name and the attribute in which to store noderefs to categories.
*
* @param aspectName
* @param attributeName
*/
public NodeRef createClassifiction(StoreRef storeRef, QName aspectName, String attributeName);
/**
* Create a new root category in the given classification
*
* @param storeRef
* @param aspectName
* @param name
* @return
*/
public NodeRef createRootCategory(StoreRef storeRef, QName aspectName, String name);
/**
* Create a new category.
*
* @param parent
* @param name
* @return
*/
public NodeRef createCategory(NodeRef parent, String name);
/**
* Delete a classification
*
* @param storeRef
* @param aspectName
*/
public void deleteClassification(StoreRef storeRef, QName aspectName);
/**
* Delete a category
*
* @param nodeRef
*/
public void deleteCategory(NodeRef nodeRef);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import org.alfresco.service.namespace.QName;
public interface NamedQueryParameterDefinition
{
/**
* Get the name of this parameter. It could be used as the well known name for the parameter.
*
* Not null
*
* @return
*/
public QName getQName();
/**
* Get the query parameter definition
* @return
*/
public QueryParameterDefinition getQueryParameterDefinition();
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
/**
* Encapsulates a query parameter
*
* @author andyh
*
*/
public class QueryParameter
{
private QName qName;
private Serializable value;
public QueryParameter(QName qName, Serializable value)
{
this.qName = qName;
this.value = value;
}
public QName getQName()
{
return qName;
}
public Serializable getValue()
{
return value;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
public interface QueryParameterDefinition extends NamedQueryParameterDefinition
{
/**
* This parameter may apply to a well known property type.
*
* May be null
*
* @return
*/
public PropertyDefinition getPropertyDefinition();
/**
* Get the property type definition for this parameter.
* It could come from the property type definition if there is one
*
* Not null
*
* @return
*/
public DataTypeDefinition getDataTypeDefinition();
/**
* Get the default value for this parameter.
*
* @return
*/
public String getDefault();
/**
* Has this parameter got a default value?
*
* @return
*/
public boolean hasDefaultValue();
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.util.List;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
/**
* An iterable result set from a searcher query. TODO: Expose meta data and XML
*
* @author andyh
*
*/
public interface ResultSet extends Iterable<ResultSetRow> // Specfic iterator
// over
// ResultSetRows
{
/**
* Get the relative paths to all the elements contained in this result set
*/
Path[] getPropertyPaths();
/**
* Get the size of the result set
*/
int length();
/**
* Get the id of the node at the given index
*/
NodeRef getNodeRef(int n);
/**
* Get the score for the node at the given position
*/
float getScore(int n);
/**
* Generate the XML form of this result set
*/
// Dom getXML(int page, int pageSize, boolean includeMetaData);
/**
* Generate as XML for Reading
*/
// Stream getStream(int page, int pageSize, boolean includeMetaData);
/**
* toString() as above but for the whole set
*/
// String toString();
// ResultSetMetaData getMetaData();
void close();
ResultSetRow getRow(int i);
List<NodeRef> getNodeRefs();
List<ChildAssociationRef> getChildAssocRefs();
ChildAssociationRef getChildAssocRef(int n);
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.namespace.QName;
/**
* A row in a result set
*
* TODO: Support for other non attribute features such as parents and path
*
* @author andyh
*
*/
public interface ResultSetRow
{
/**
* Get the values of all available node properties
*
* @return
*/
public Map<Path, Serializable> getValues();
/**
* Get a node property by path
*
* @param path
* @return
*/
public Serializable getValue(Path path);
/**
* Get a node value by name
*
* @param qname
* @return
*/
public Serializable getValue(QName qname);
/**
* The refernce to the node that equates to this row in the result set
*
* @return
*/
public NodeRef getNodeRef();
/**
* Get the score for this row in the result set
*
* @return
*/
public float getScore(); // Score is score + rank + potentially other
// stuff
/**
* Get the containing result set
*
* @return
*/
public ResultSet getResultSet();
/**
* Return the QName of the node in the context in which it was found.
* @return
*/
public QName getQName();
/**
* Get the position of this row in the containing set.
* @return
*/
public int getIndex();
/**
* Return the child assoc ref for this row
* @return
*/
public ChildAssociationRef getChildAssocRef();
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.util.ArrayList;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* This class provides parameters to define a search.
*
* @author Andy Hind
*/
public class SearchParameters extends SearchStatement
{
public static final SortDefinition SORT_IN_DOCUMENT_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, true);
public static final SortDefinition SORT_IN_DOCUMENT_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, false);
public static final SortDefinition SORT_IN_SCORE_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, false);
public static final SortDefinition SORT_IN_SCORE_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, true);
public enum Operator
{
OR, AND
}
public static final Operator OR = Operator.OR;
public static final Operator AND = Operator.AND;
private ArrayList<StoreRef> stores = new ArrayList<StoreRef>(1);
private ArrayList<Path> attributePaths = new ArrayList<Path>(1);
private ArrayList<QueryParameterDefinition> queryParameterDefinitions = new ArrayList<QueryParameterDefinition>(1);
private boolean excludeDataInTheCurrentTransaction = false;
private ArrayList<SortDefinition> sortDefinitions = new ArrayList<SortDefinition>(1);
private Operator defaultOperator = Operator.OR;
public SearchParameters()
{
super();
}
/**
* Set the stores to be supported - currently there can be only one
*
* @param store
*/
public void addStore(StoreRef store)
{
if(stores.size() != 0)
{
throw new IllegalStateException("At the moment, there can only be one store set for the search");
}
stores.add(store);
}
/**
* Add paths for attributes in the result set
*
* @param attributePath
*/
public void addAttrbutePath(Path attributePath)
{
attributePaths.add(attributePath);
}
/**
* Add parameter definitions for the query - used to parameterise the query string
*
* @param queryParameterDefinition
*/
public void addQueryParameterDefinition(QueryParameterDefinition queryParameterDefinition)
{
queryParameterDefinitions.add(queryParameterDefinition);
}
/**
* If true, any data in the current transaction will be ignored in the search.
* You will not see anything you have added in the current transaction.
*
* @param excludeDataInTheCurrentTransaction
*/
public void excludeDataInTheCurrentTransaction(boolean excludeDataInTheCurrentTransaction)
{
this.excludeDataInTheCurrentTransaction = excludeDataInTheCurrentTransaction;
}
/**
* Add a sort to the query (for those query languages that do not support it directly)
*
* @param field - this is intially a direct attribute on a node not an attribute on the parent etc
* TODO: It could be a relative path at some time.
*
*
* @param ascending
*/
public void addSort(String field, boolean ascending)
{
addSort(new SortDefinition(SortDefinition.SortType.FIELD, field, ascending));
}
public void addSort(SortDefinition sortDefinition)
{
sortDefinitions.add(sortDefinition);
}
/**
* A helper class for sort definition
* @author andyh
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public static class SortDefinition
{
public enum SortType {FIELD, DOCUMENT, SCORE};
SortType sortType;
String field;
boolean ascending;
SortDefinition(SortType sortType, String field, boolean ascending)
{
this.sortType = sortType;
this.field = field;
this.ascending = ascending;
}
public boolean isAscending()
{
return ascending;
}
public String getField()
{
return field;
}
public SortType getSortType()
{
return sortType;
}
}
public ArrayList<Path> getAttributePaths()
{
return attributePaths;
}
public boolean excludeDataInTheCurrentTransaction()
{
return excludeDataInTheCurrentTransaction;
}
public ArrayList<QueryParameterDefinition> getQueryParameterDefinitions()
{
return queryParameterDefinitions;
}
public ArrayList<SortDefinition> getSortDefinitions()
{
return sortDefinitions;
}
public ArrayList<StoreRef> getStores()
{
return stores;
}
public void setDefaultOperator(Operator defaultOperator)
{
this.defaultOperator = defaultOperator;
}
public Operator getDefaultOperator()
{
return defaultOperator;
}
}

View File

@@ -0,0 +1,264 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
import java.io.Serializable;
import java.util.List;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.XPathException;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* This encapsulates the execution of search against different indexing
* mechanisms.
*
* Canned queries have been translated into the query string by this stage.
* Handling of parameterisation is left to the implementation.
*
* @author Andy hind
*
*/
public interface SearchService
{
public static final String LANGUAGE_LUCENE = "lucene";
public static final String LANGUAGE_XPATH = "xpath";
public static final String LANGUAGE_JCR_XPATH = "jcr-xpath";
/**
* Search against a store.
*
* @param store -
* the store against which to search
* @param language -
* the query language
* @param query -
* the query string - which may include parameters
* @param attributePaths -
* explicit list of attributes/properties to extract for the
* selected nodes in xpath style syntax
* @param queryParameterDefinition -
* query parameter definitions - the default value is used for
* the value.
* @return Returns the query results
*/
public ResultSet query(StoreRef store, String language, String query, Path[] attributePaths,
QueryParameterDefinition[] queryParameterDefinitions);
/**
* Search against a store. Pulls back all attributes on each node. Does not
* allow parameterisation.
*
* @param store -
* the store against which to search
* @param language -
* the query language
* @param query -
* the query string - which may include parameters
* @return Returns the query results
*/
public ResultSet query(StoreRef store, String language, String query);
/**
* Search against a store.
*
* @param store -
* the store against which to search
* @param language -
* the query language
* @param query -
* the query string - which may include parameters
* @param queryParameterDefinition -
* query parameter definitions - the default value is used for
* the value.
* @return Returns the query results
*/
public ResultSet query(StoreRef store, String language, String query,
QueryParameterDefinition[] queryParameterDefintions);
/**
* Search against a store.
*
* @param store -
* the store against which to search
* @param language -
* the query language
* @param query -
* the query string - which may include parameters
* @param attributePaths -
* explicit list of attributes/properties to extract for the
* selected nodes in xpath style syntax
* @return Returns the query results
*/
public ResultSet query(StoreRef store, String language, String query, Path[] attributePaths);
/**
* Execute a canned query
*
* @param store -
* the store against which to search
* @param queryId -
* the query identifier
* @param queryParameters -
* parameterisation for the canned query
* @return Returns the query results
*/
public ResultSet query(StoreRef store, QName queryId, QueryParameter[] queryParameters);
/**
* Search using the given SearchParameters
*/
public ResultSet query(SearchParameters searchParameters);
/**
* Select nodes using an xpath expression.
*
* @param contextNodeRef -
* the context node for relative expressions etc
* @param xpath -
* the xpath string to evaluate
* @param parameters -
* parameters to bind in to the xpath expression
* @param namespacePrefixResolver -
* prefix to namespace mappings
* @param followAllParentLinks -
* if false ".." follows only the primary parent links, if true
* it follows all
* @return a list of all the child assoc relationships to the selected nodes
*/
public List<NodeRef> selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters,
NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks)
throws InvalidNodeRefException, XPathException;
/**
* Select nodes using an xpath expression.
*
* @param contextNodeRef -
* the context node for relative expressions etc
* @param xpath -
* the xpath string to evaluate
* @param parameters -
* parameters to bind in to the xpath expression
* @param namespacePrefixResolver -
* prefix to namespace mappings
* @param followAllParentLinks -
* if false ".." follows only the primary parent links, if true
* it follows all
* @param langauage -
* the xpath variant
* @return a list of all the child assoc relationships to the selected nodes
*/
public List<NodeRef> selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters,
NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks, String language)
throws InvalidNodeRefException, XPathException;
/**
* Select properties using an xpath expression
*
* @param contextNodeRef -
* the context node for relative expressions etc
* @param xpath -
* the xpath string to evaluate
* @param parameters -
* parameters to bind in to the xpath expression
* @param namespacePrefixResolver -
* prefix to namespace mappings
* @param followAllParentLinks -
* if false ".." follows only the primary parent links, if true
* it follows all
* @return a list of property values
*/
public List<Serializable> selectProperties(NodeRef contextNodeRef, String xpath,
QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver,
boolean followAllParentLinks) throws InvalidNodeRefException, XPathException;
/**
* Select properties using an xpath expression
*
* @param contextNodeRef -
* the context node for relative expressions etc
* @param xpath -
* the xpath string to evaluate
* @param parameters -
* parameters to bind in to the xpath expression
* @param namespacePrefixResolver -
* prefix to namespace mappings
* @param followAllParentLinks -
* if false ".." follows only the primary parent links, if true
* it follows all
* @param langauage -
* the xpath variant
* @return a list of property values
*/
public List<Serializable> selectProperties(NodeRef contextNodeRef, String xpath,
QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver,
boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException;
/**
* Search for string pattern in both the node text (if present) and node
* properties
*
* @param nodeRef
* the node to get
* @param propertyQName
* the name of the property
* @param googleLikePattern
* a Google-like pattern to search for in the property value
* @return Returns true if the pattern could be found - uses the default OR operator
*/
public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern)
throws InvalidNodeRefException;
/**
* Search for string pattern in both the node text (if present) and node
* properties
*
* @param nodeRef
* the node to get
* @param propertyQName
* the name of the property
* @param googleLikePattern
* a Google-like pattern to search for in the property value
* @return Returns true if the pattern could be found
*/
public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern, SearchParameters.Operator defaultOperator)
throws InvalidNodeRefException;
/**
* Search for string pattern in both the node text (if present) and node
* properties
*
* @param nodeRef
* the node to get
* @param propertyQName
* the name of the property (mandatory)
* @param sqlLikePattern
* a SQL-like pattern to search for
* @param includeFTS -
* include full text search matches in the like test
* @return Returns true if the pattern could be found
*/
public boolean like(NodeRef nodeRef, QName propertyQName, String sqlLikePattern, boolean includeFTS)
throws InvalidNodeRefException;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.search;
/**
* A search string and language.
*
* @author Andy Hind
*/
public class SearchStatement
{
private String language;
private String query;
SearchStatement()
{
super();
}
SearchStatement(String language, String query)
{
this.language = language;
this.query = query;
}
public String getLanguage()
{
return language;
}
public String getQuery()
{
return query;
}
public void setLanguage(String language)
{
this.language = language;
}
public void setQuery(String query)
{
this.query = query;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
/**
* The interface used to support reporting back if permissions are allowed or
* denied.
*
* @author Andy Hind
*/
public interface AccessPermission
{
/**
* The permission.
*
* @return
*/
public String getPermission();
/**
* Get the Access enumeration value
*
* @return
*/
public AccessStatus getAccessStatus();
/**
* Get the authority to which this permission applies.
*
* @return
*/
public String getAuthority();
/**
* Get the type of authority to which this permission applies.
*
* @return
*/
public AuthorityType getAuthorityType();
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
/**
* Enumeration used to indicate access status.
*
* @author Andy Hind
*/
public enum AccessStatus
{
DENIED, ALLOWED
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
import org.alfresco.repo.security.authentication.AuthenticationException;
/**
* The authentication service defines the API for managing authentication information
* against a user id.
*
* @author Andy Hind
*
*/
public interface AuthenticationService
{
/**
* Create an authentication for the given user.
*
* @param userName
* @param password
* @throws AuthenticationException
*/
public void createAuthentication(String userName, char[] password) throws AuthenticationException;
/**
* Update the login information for the user (typically called by the user)
*
* @param userName
* @param oldPassword
* @param newPassword
* @throws AuthenticationException
*/
public void updateAuthentication(String userName, char[] oldPassword, char[] newPassword) throws AuthenticationException;
/**
* Set the login information for a user (typically called by an admin user)
*
* @param userName
* @param newPassword
* @throws AuthenticationException
*/
public void setAuthentication(String userName, char[] newPassword) throws AuthenticationException;
/**
* Delete an authentication entry
*
* @param userName
* @throws AuthenticationException
*/
public void deleteAuthentication(String userName) throws AuthenticationException;
/**
* Enable or disable an authentication entry
*
* @param userName
* @param enabled
*/
public void setAuthenticationEnabled(String userName, boolean enabled) throws AuthenticationException;
/**
* Is an authentication enabled or disabled?
*
* @param userName
* @return
*/
public boolean getAuthenticationEnabled(String userName) throws AuthenticationException;
/**
* Carry out an authentication attempt. If successful the user is set to the current user.
* The current user is a part of the thread context.
*
* @param userName
* @param password
* @throws AuthenticationException
*/
public void authenticate(String userName, char[] password) throws AuthenticationException;
/**
* Get the name of the currently authenticated user.
*
* @return
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException;
/**
* Invalidate any tickets held by the user.
*
* @param userName
* @throws AuthenticationException
*/
public void invalidateUserSession(String userName) throws AuthenticationException;
/**
* Invalidate a single ticket by ID
*
* @param ticket
* @throws AuthenticationException
*/
public void invalidateTicket(String ticket) throws AuthenticationException;
/**
* Validate a ticket. Set the current user name accordingly.
*
* @param ticket
* @throws AuthenticationException
*/
public void validate(String ticket) throws AuthenticationException;
/**
* Get the current ticket as a string
* @return
*/
public String getCurrentTicket();
/**
* Remove the current security information
*
*/
public void clearCurrentSecurityContext();
/**
* Is the current user the system user?
*
* @return
*/
public boolean isCurrentUserTheSystemUser();
}

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
import java.util.Set;
/**
* The service that encapsulates authorities granted to users.
*
* This service will refuse to create any user authorities. These should be
* managed using the AuthenticationService and PersonServce. Methods that try to
* change alter users will throw an exception.
*
* A string key is used to identify the authority. These follow the contract
* defined in AuthorityType. If there are entities linked to these authorities
* this key should be used to find them, as userName is used link user and
* person.
*
* @author Andy Hind
*/
public interface AuthorityService
{
/**
* Check of the current user has admin authority.
*
* There is no contract for who should have this authority, only that it can
* be tested here. It could be determined by group membership, role,
* authentication mechanism, ...
*
* @return true if the currently authenticated user has the admin authority
*/
public boolean hasAdminAuthority();
/**
* Get the authorities for the current user
*
* @return
*/
public Set<String> getAuthorities();
/**
* Get all authorities by type.
*
* @param type -
* the type of authorities.
* @return
*/
public Set<String> getAllAuthorities(AuthorityType type);
/**
* Get all root authorities by type. Root authorities are ones that were
* created without an authority as the parent authority;
*
* @param type -
* the type of the authority
* @return
*/
public Set<String> getAllRootAuthorities(AuthorityType type);
/**
* Create an authority. If the parent is null thisw method creates a root
* authority.
*
* @param type -
* the type of the authority
* @param parentName -
* the name of the parent authority. If this is null then a root
* authority is created.
* @param shortName -
* the short name of the authority to create
*
* @return the name of the authority (this will be the prefix, if any
* associated with the type appended with the short name)
*/
public String createAuthority(AuthorityType type, String parentName, String shortName);
/**
* Set an authority to include another authority. For example, adding a
* group to a group or adding a user to a group.
*
* @param parentName -
* the string identifier for the parent.
* @param childName -
* the string identifier for the child.
*/
public void addAuthority(String parentName, String childName);
/**
* Remove an authority as a member of another authority. The child authority
* will still exist. If the child authority was not created as a root
* authority and you remove its creation link, it will be moved to a root
* authority. If you want rid of it, use delete.
*
* @param parentName -
* the string identifier for the parent.
* @param childName -
* the string identifier for the child.
*/
public void removeAuthority(String parentName, String childName);
/**
* Delete an authority and all its relationships.
*
* @param name
*/
public void deleteAuthority(String name);
/**
* Get all the authorities that are contained by the given authority.
*
* For a group you could get all the authorities it contains, just the users
* it contains or just the other groups it includes.
*
* @param type -
* if not null, limit to the type of authority specified
* @param name -
* the name of the containing authority
* @param immediate -
* if true, limit the depth to just immediate child, if false
* find authorities at any depth
* @return
*/
public Set<String> getContainedAuthorities(AuthorityType type, String name, boolean immediate);
/**
* Get the authorities that contain the given authority
*
* For example, this can be used find out all the authorities that contain a
* user.
*
* @param type -
* if not null, limit to the type of authority specified
* @param name -
* the name of the authority for which the containing authorities
* are required.
* @param immediate -
* limit to immediate parents or any ancestor.
* @return
*/
public Set<String> getContainingAuthorities(AuthorityType type, String name, boolean immediate);
/**
* Extract the short name of an authority from its full identifier.
*
* @param name
* @return
*/
public String getShortName(String name);
/**
* Create the full identifier for an authority given its short name and
* type.
*
* @param type
* @param shortName
* @return
*/
public String getName(AuthorityType type, String shortName);
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
/**
* The types of authority that are available.
* <p>
* <p>
* Available types are:
* <ol>
* <li>USER - an authority that identifies a user
* <li>GROUP - an authority that identifies a group
* <li>OWNER - the special authority that applies to the owner of a node
* <li>EVERYONE - the special authority that is interpreted as everyone
* <li>GUEST - the special authority that applies to a GUEST (An unknown,
* unauthenticated user)
* </ol>
*
* @author Andy Hind
*/
public enum AuthorityType
{
ADMIN
{
public boolean isFixedString()
{
return true;
}
public String getFixedString()
{
return PermissionService.ADMINISTRATOR_AUTHORITY;
}
public boolean isPrefixed()
{
return false;
}
public String getPrefixString()
{
return "";
}
},
EVERYONE
{
public boolean isFixedString()
{
return true;
}
public String getFixedString()
{
return PermissionService.ALL_AUTHORITIES;
}
public boolean isPrefixed()
{
return false;
}
public String getPrefixString()
{
return "";
}
},
OWNER
{
public boolean isFixedString()
{
return true;
}
public String getFixedString()
{
return PermissionService.OWNER_AUTHORITY;
}
public boolean isPrefixed()
{
return false;
}
public String getPrefixString()
{
return "";
}
},
GUEST
{
public boolean isFixedString()
{
return true;
}
public String getFixedString()
{
return PermissionService.GUEST;
}
public boolean isPrefixed()
{
return false;
}
public String getPrefixString()
{
return "";
}
},
GROUP
{
public boolean isFixedString()
{
return false;
}
public String getFixedString()
{
return "";
}
public boolean isPrefixed()
{
return true;
}
public String getPrefixString()
{
return PermissionService.GROUP_PREFIX;
}
},
ROLE
{
public boolean isFixedString()
{
return false;
}
public String getFixedString()
{
return "";
}
public boolean isPrefixed()
{
return true;
}
public String getPrefixString()
{
return PermissionService.ROLE_PREFIX;
}
},
USER
{
public boolean isFixedString()
{
return false;
}
public String getFixedString()
{
return "";
}
public boolean isPrefixed()
{
return false;
}
public String getPrefixString()
{
return "";
}
};
public abstract boolean isFixedString();
public abstract String getFixedString();
public abstract boolean isPrefixed();
public abstract String getPrefixString();
public boolean equals(String authority)
{
return equals(getAuthorityType(authority));
}
public static AuthorityType getAuthorityType(String authority)
{
AuthorityType authorityType;
if (authority.equals(PermissionService.ADMINISTRATOR_AUTHORITY))
{
authorityType = AuthorityType.ADMIN;
}
if (authority.equals(PermissionService.ALL_AUTHORITIES))
{
authorityType = AuthorityType.EVERYONE;
}
else if (authority.equals(PermissionService.OWNER_AUTHORITY))
{
authorityType = AuthorityType.OWNER;
}
else if (authority.equals(PermissionService.GUEST))
{
authorityType = AuthorityType.GUEST;
}
else if (authority.startsWith(PermissionService.GROUP_PREFIX))
{
authorityType = AuthorityType.GROUP;
}
else if (authority.startsWith(PermissionService.ROLE_PREFIX))
{
authorityType = AuthorityType.ROLE;
}
else
{
authorityType = AuthorityType.USER;
}
return authorityType;
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Service support around managing ownership.
*
* @author Andy Hind
*/
public interface OwnableService
{
/**
* Get the username of the owner of the given object.
*
* @param nodeRef
* @return the username or null if the object has no owner
*/
public String getOwner(NodeRef nodeRef);
/**
* Set the owner of the object.
*
* @param nodeRef
* @param userName
*/
public void setOwner(NodeRef nodeRef, String userName);
/**
* Set the owner of the object to be the current user.
*
* @param nodeRef
*/
public void takeOwnership(NodeRef nodeRef);
/**
* Does the given node have an owner?
*
* @param nodeRef
* @return
*/
public boolean hasOwner(NodeRef nodeRef);
}

View File

@@ -0,0 +1,233 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.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 org.alfresco.service.cmr.security;
import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* The public API for a permission service
*
* The implementation may be changed in the application configuration
*
* @author Andy Hind
*/
public interface PermissionService
{
public static final String ROLE_PREFIX = "ROLE_";
public static final String GROUP_PREFIX = "GROUP_";
public static final String ALL_AUTHORITIES = "GROUP_EVERYONE";
public static final String OWNER_AUTHORITY = "ROLE_OWNER";
public static final String LOCK_OWNER_AUTHORITY = "ROLE_LOCK_OWNER";
public static final String ADMINISTRATOR_AUTHORITY = "ROLE_ADMINISTRATOR";
public static final String ALL_PERMISSIONS = "All";
public static final String FULL_CONTROL = "FullControl";
public static final String READ = "Read";
public static final String WRITE = "Write";
public static final String DELETE = "Delete";
public static final String ADD_CHILDREN = "AddChildren";
public static final String READ_PROPERTIES = "ReadProperties";
public static final String READ_CHILDREN = "ReadChildren";
public static final String WRITE_PROPERTIES = "WriteProperties";
public static final String DELETE_NODE = "DeleteNode";
public static final String DELETE_CHILDREN = "DeleteChildren";
public static final String CREATE_CHILDREN = "CreateChildren";
public static final String LINK_CHILDREN = "LinkChildren";
public static final String DELETE_ASSOCIATIONS = "DeleteAssociations";
public static final String READ_ASSOCIATIONS = "ReadAssociations";
public static final String CREATE_ASSOCIATIONS = "CreateAssociations";
public static final String READ_PERMISSIONS = "ReadPermissions";
public static final String CHANGE_PERMISSIONS = "ChangePermissions";
public static final String EXECUTE = "Execute";
public static final String READ_CONTENT = "ReadContent";
public static final String WRITE_CONTENT = "WriteContent";
public static final String EXECUTE_CONTENT = "ExecuteContent";
public static final String TAKE_OWNERSHIP = "TakeOwnership";
public static final String SET_OWNER = "SetOwner";
public static final String COORDINATOR = "Coordinator";
public static final String CONTRIBUTOR = "Contributor";
public static final String EDITOR = "Editor";
public static final String GUEST = "Guest";
public static final String LOCK = "Lock";
public static final String UNLOCK = "Unlock";
public static final String CHECK_OUT = "CheckOut";
public static final String CHECK_IN = "CheckIn";
public static final String CANCEL_CHECK_OUT = "CancelCheckOut";
/**
* Get the Owner Authority
*
* @return the owner authority
*/
public String getOwnerAuthority();
/**
* Get the All Authorities
*
* @return the All authorities
*/
public String getAllAuthorities();
/**
* Get the All Permission
*
* @return the All permission
*/
public String getAllPermission();
/**
* Get all the AccessPermissions that are granted/denied to the current
* authentication for the given node
*
* @param nodeRef -
* the reference to the node
* @return the set of allowed permissions
*/
public Set<AccessPermission> getPermissions(NodeRef nodeRef);
/**
* Get all the AccessPermissions that are set for anyone for the
* given node
*
* @param nodeRef -
* the reference to the node
* @return the set of allowed permissions
*/
public Set<AccessPermission> getAllSetPermissions(NodeRef nodeRef);
/**
* Get the permissions that can be set for a given node
*
* @param nodeRef
* @return
*/
public Set<String> getSettablePermissions(NodeRef nodeRef);
/**
* Get the permissions that can be set for a given type
*
* @param nodeRef
* @return
*/
public Set<String> getSettablePermissions(QName type);
/**
* Check that the given authentication has a particular permission for the
* given node. (The default behaviour is to inherit permissions)
*
* @param nodeRef
* @param perm
* @return
*/
public AccessStatus hasPermission(NodeRef nodeRef, String perm);
/**
* Delete all the permission assigned to the node
*
* @param nodeRef
*/
public void deletePermissions(NodeRef nodeRef);
/**
* Delete all permission for the given authority.
*
* @param nodeRef
* @param authority
*/
public void clearPermission(NodeRef nodeRef, String authority);
/**
* Find and delete a permission by node, authentication and permission
* definition.
*
* @param nodeRef
* @param authority
* @param perm
*/
public void deletePermission(NodeRef nodeRef, String authority, String perm, boolean allow);
/**
* Set a specific permission on a node.
*
* @param nodeRef
* @param authority
* @param perm
* @param allow
*/
public void setPermission(NodeRef nodeRef, String authority, String perm, boolean allow);
/**
* Set the global inheritance behaviour for permissions on a node.
*
* @param nodeRef
* @param inheritParentPermissions
*/
public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions);
/**
* Return the global inheritance behaviour for permissions on a node.
*
* @param nodeRef
* @return inheritParentPermissions
*/
public boolean getInheritParentPermissions(NodeRef nodeRef);
}

Some files were not shown because too many files have changed in this diff Show More