001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.model; 017 018import java.util.HashSet; 019import java.util.Optional; 020import java.util.Set; 021 022import org.ametys.plugins.repository.AmetysObject; 023import org.ametys.plugins.repository.data.ametysobject.DataAwareAmetysObject; 024import org.ametys.runtime.model.ModelHelper; 025import org.ametys.runtime.model.type.DataContext; 026 027/** 028 * Object that gives some context for repository data manipulation 029 */ 030public class RepositoryDataContext extends DataContext 031{ 032 private Optional<? extends DataAwareAmetysObject> _object = Optional.empty(); 033 private Optional<? extends DataAwareAmetysObject> _rootObject = Optional.empty(); 034 035 private Set<String> _externalizableData = new HashSet<>(); 036 private boolean _copyExternalMetadata; 037 038 /** 039 * Creates a new instance of a {@link RepositoryDataContext} 040 */ 041 protected RepositoryDataContext() 042 { 043 // Empty constructor 044 } 045 046 /** 047 * Creates a new instance of a {@link RepositoryDataContext} from another {@link DataContext} 048 * @param context the data context to copy 049 */ 050 protected RepositoryDataContext(DataContext context) 051 { 052 super(context); 053 if (context instanceof RepositoryDataContext repositoryContext) 054 { 055 withObject(repositoryContext.getObject().orElse(null)); 056 _withRootObject(repositoryContext._getRootObject().orElse(null)); 057 058 withExternalizableData(repositoryContext.getExternalizableData()); 059 withExternalMetadataInCopy(repositoryContext.copyExternalMetadata()); 060 } 061 } 062 063 /** 064 * Creates a new instance of a {@link RepositoryDataContext} 065 * @return the created instance 066 */ 067 public static RepositoryDataContext newInstance() 068 { 069 return new RepositoryDataContext(); 070 } 071 072 /** 073 * Creates a new instance of a {@link RepositoryDataContext} from another {@link DataContext}. 074 * It can be the same implementation or another one, but it will be casted to the current implementation. 075 * @param context the data context to copy 076 * @return the created instance 077 */ 078 public static RepositoryDataContext newInstance(DataContext context) 079 { 080 return new RepositoryDataContext(context); 081 } 082 083 /** 084 * Creates a new instance of a {@link RepositoryDataContext}, with the current context values 085 * @return the created instance 086 */ 087 @Override 088 public RepositoryDataContext cloneContext() 089 { 090 return newInstance(this); 091 } 092 093 /** 094 * Retrieves the object from which the data path is computed 095 * @param <T> Type of the object 096 * @return the object 097 */ 098 @SuppressWarnings("unchecked") 099 public <T extends DataAwareAmetysObject> Optional<T> getObject() 100 { 101 return (Optional<T>) _object; 102 } 103 104 /** 105 * Retrieves the identifier of the object 106 * @return the object's identifier 107 */ 108 public Optional<String> getObjectId() 109 { 110 return _object.map(AmetysObject::getId); 111 } 112 113 /** 114 * Set the object from which the data path is computed 115 * @param <T> the type of the retrieved {@link DataContext} 116 * @param object the object to set 117 * @return the current {@link DataContext} 118 */ 119 @SuppressWarnings("unchecked") 120 public <T extends RepositoryDataContext> T withObject(DataAwareAmetysObject object) 121 { 122 _object = Optional.ofNullable(object); 123 124 if (_rootObject.isEmpty()) 125 { 126 _withRootObject(object); 127 } 128 129 return (T) this; 130 } 131 132 /** 133 * Retrieves the object from which the full data path is computed 134 * @param <T> Type of the root object 135 * @return the root object 136 */ 137 @SuppressWarnings("unchecked") 138 protected <T extends DataAwareAmetysObject> Optional<T> _getRootObject() 139 { 140 return (Optional<T>) _rootObject; 141 } 142 143 /** 144 * Retrieves the identifier of the root object 145 * @return the root object's identifier 146 */ 147 public Optional<String> getRootObjectId() 148 { 149 return _rootObject.map(AmetysObject::getId); 150 } 151 152 /** 153 * Set the object from which the full data path is computed 154 * @param <T> the type of the retrieved {@link DataContext} 155 * @param rootObject the root object to set 156 * @return the current {@link DataContext} 157 */ 158 @SuppressWarnings("unchecked") 159 protected <T extends RepositoryDataContext> T _withRootObject(DataAwareAmetysObject rootObject) 160 { 161 _rootObject = Optional.ofNullable(rootObject); 162 return (T) this; 163 } 164 165 /** 166 * Retrieves the externalizable data 167 * @return the externalizable data 168 */ 169 public Set<String> getExternalizableData() 170 { 171 return _externalizableData; 172 } 173 174 /** 175 * Check if the current data is externalizable 176 * @return <code>true</code> if the data is externalizable, <code>false</code> otherwise 177 */ 178 public boolean isDataExternalizable() 179 { 180 String dataPath = getDataPath(); 181 String definitionPath = ModelHelper.getDefinitionPathFromDataPath(dataPath); 182 return _externalizableData.contains(definitionPath); 183 } 184 185 /** 186 * Sets the externalizable data 187 * @param <T> the type of the retrieved {@link DataContext} 188 * @param externalizableData the externalizable data to set 189 * @return the current {@link RepositoryDataContext} 190 */ 191 @SuppressWarnings("unchecked") 192 public <T extends RepositoryDataContext> T withExternalizableData(Set<String> externalizableData) 193 { 194 _externalizableData = externalizableData; 195 return (T) this; 196 } 197 198 /** 199 * Check if the external metadata (alternative and status) should be copied 200 * @return <code>true</code> if the external metadata should be copied, <code>false</code> otherwise 201 */ 202 public boolean copyExternalMetadata() 203 { 204 return _copyExternalMetadata; 205 } 206 207 /** 208 * Set to <code>true</code> to copy the external metadata (alternative and status) (default to <code>false</code>) 209 * @param <T> the type of the retrieved {@link DataContext} 210 * @param copyExternalMetadata <code>true</code> to copy the external metadata, <code>false</code> otherwise 211 * @return the current {@link RepositoryDataContext} 212 */ 213 @SuppressWarnings("unchecked") 214 public <T extends RepositoryDataContext> T withExternalMetadataInCopy(boolean copyExternalMetadata) 215 { 216 _copyExternalMetadata = copyExternalMetadata; 217 return (T) this; 218 } 219}