001/**
002 * Copyright 2010 The Kuali Foundation Licensed under the
003 * Educational Community License, Version 2.0 (the "License"); you may
004 * not use this file except in compliance with the License. You may
005 * obtain a copy of the License at
006 *
007 * http://www.osedu.org/licenses/ECL-2.0
008 *
009 * Unless required by applicable law or agreed to in writing,
010 * software distributed under the License is distributed on an "AS IS"
011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012 * or implied. See the License for the specific language governing
013 * permissions and limitations under the License.
014 */
015
016package org.kuali.student.r1.common.assembly.util;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.kuali.student.r1.common.assembly.data.Data;
022import org.kuali.student.r1.common.assembly.data.Metadata;
023import org.kuali.student.r1.common.assembly.data.QueryPath;
024import org.kuali.student.r1.common.assembly.data.Data.DataType;
025import org.kuali.student.r1.common.assembly.data.Data.Key;
026import org.kuali.student.r1.common.assembly.helper.PropertyEnum;
027import org.kuali.student.r1.common.assembly.helper.RuntimeDataHelper;
028
029public class AssemblerUtils {
030        public enum VersionProperties implements PropertyEnum {
031                TYPENAME("typeName"), ID("id"), VERSION_INDICATOR("versionIndicator");
032
033                private final String key;
034
035                private VersionProperties(final String key) {
036                        this.key = key;
037                }
038
039                @Override
040                public String getKey() {
041                        return this.key;
042                }
043        }
044
045        public static String getVersionIndicator(Data data) {
046                String result = null;
047                Data versions = getVersions(data);
048                if (versions == null) {
049                        return null;
050                }
051                if (versions.size() > 0) {
052                        Data v = versions.get(0);
053                        if (v != null) {
054                                result = v.get(VersionProperties.VERSION_INDICATOR.getKey());
055                        }
056                }
057                return result;
058        }
059
060        public static String getVersionIndicator(Data data, String typeName) {
061                return getVersionIndicator(data, typeName, null);
062        }
063
064        public static String getVersionIndicator(Data data, String typeName, String id) {
065                Data version = getVersionData(data, typeName, id);
066                if (version == null) {
067                        return null;
068                } else {
069                        return version.get(VersionProperties.VERSION_INDICATOR.getKey());
070                }
071        }
072
073        public static Data getVersionData(Data data, String typeName, String id) {
074                Data result = null;
075                Data versions = getVersions(data);
076                if (versions == null) {
077                        return null;
078                }
079                for (Data.Property p : versions) {
080                        Data v = p.getValue();
081                        if (typeName.equals((String) v.get(VersionProperties.TYPENAME.getKey())) && (id == null || id.equals((String) v.get(VersionProperties.ID.getKey())))) {
082                                result = v;
083                                break;
084                        }
085                }
086                return result;
087
088        }
089
090        public static Data getVersions(Data data) {
091                Data result = null;
092
093                if (data != null) {
094                        // TODO need a "standard properties" enum for values that could be present on any object?
095                        Data runtime = data.get("_runtimeData");
096                        if (runtime != null) {
097                                result = runtime.get(RuntimeDataHelper.Properties.VERSIONS.getKey());
098                        }
099                }
100
101                return result;
102        }
103
104        public static void addVersionIndicator(Data data, String typeName, String id, String version) {
105                Data existing = getVersionData(data, typeName, id);
106                if (existing == null) {
107                        Data d = new Data();
108                        d.set(VersionProperties.TYPENAME.getKey(), typeName);
109                        d.set(VersionProperties.ID.getKey(), id);
110                        d.set(VersionProperties.VERSION_INDICATOR.getKey(), version);
111                        Data versions = getVersions(data);
112                        if (versions == null) {
113                                versions = new Data();
114                                setVersions(data, versions);
115                        }
116                        versions.add(d);
117                } else {
118                        existing.set(VersionProperties.VERSION_INDICATOR.getKey(), version);
119                }
120        }
121        public static void setVersions(Data data, Data versions) {
122                if (data != null) {
123                        // TODO need a "standard properties" enum for values that could be present on any object?
124                        Data runtime = data.get("_runtimeData");
125                        if (runtime == null) {
126                                runtime = new Data();
127                                data.set("_runtimeData", runtime);
128                        }
129                        runtime.set(RuntimeDataHelper.Properties.VERSIONS.getKey(), versions);
130                }
131        }
132
133        public static boolean isCreated(Data data) {
134                return isFlagSet(data, RuntimeDataHelper.Properties.CREATED.getKey());
135        }
136
137        public static boolean isDeleted(Data data) {
138                return isFlagSet(data, RuntimeDataHelper.Properties.DELETED.getKey());
139        }
140
141        public static boolean isUpdated(Data data) {
142                return isFlagSet(data, RuntimeDataHelper.Properties.UPDATED.getKey());
143        }
144
145        public static boolean isModified(Data data) {
146                return isCreated(data) || isUpdated(data) || isDeleted(data); //|| isFlagSet(data, RuntimeDataHelper.Properties.DIRTY.getKey());
147        }
148
149        public static void setCreated(Data data, boolean flag) {
150                setFlag(data, RuntimeDataHelper.Properties.CREATED.getKey(), flag);
151        }
152
153        public static void setDeleted(Data data, boolean flag) {
154                setFlag(data, RuntimeDataHelper.Properties.DELETED.getKey(), flag);
155        }
156
157        public static void setUpdated(Data data, boolean flag) {
158                setFlag(data, RuntimeDataHelper.Properties.UPDATED.getKey(), flag);
159        }
160
161        private static void setFlag(Data data, String key, Boolean flag) {
162                if (data != null) {
163                        Data runtime = data.get("_runtimeData");
164                        if (runtime == null) {
165                                runtime = new Data();
166                                data.set("_runtimeData", runtime);
167                        }
168                        runtime.set(key, flag);
169                }
170        }
171        private static boolean isFlagSet(Data data, String key) {
172                boolean result = false;
173
174                if (data != null) {
175                        Data runtime = data.get("_runtimeData");
176                        if (runtime != null) {
177                                result = runtime.get(key) != null && (Boolean) runtime.get(key);
178                        }
179                }
180
181                return result;
182        }
183
184
185         public static List<QueryPath> findDirtyElements(Data data) {
186             List<QueryPath> results = new ArrayList<QueryPath>();
187             _findDirtyElements(data, results, new QueryPath());
188             return results;
189         }
190         private static void _findDirtyElements(Data data, List<QueryPath> results, QueryPath currentFrame) {
191             if (data == null) {
192                 return;
193             }
194
195             Data flags = getDirtyFlags(data);
196             if (flags != null && flags.size() > 0) {
197                 for (Data.Property p : flags) {
198                     QueryPath q = new QueryPath();
199                     q.addAll(currentFrame);
200                     Key key = p.getWrappedKey();
201                     q.add(key);
202                     results.add(q);
203                 }
204             }
205
206             for (Data.Property p : data) {
207                 if (p.getValueType().equals(Data.class) && p.getValue() != null) {
208                        QueryPath q = new QueryPath();
209                        q.addAll(currentFrame);
210                        Key key = p.getWrappedKey();
211                        q.add(key);
212
213                        _findDirtyElements((Data) p.getValue(), results, q);
214                 }
215             }
216         }
217         public static Data getDirtyFlags(Data data) {
218             Data result = null;
219             Data runtime = data.get("_runtimeData");
220             if (runtime != null) {
221                 result = runtime.get("dirty");
222
223             }
224             return result;
225         }
226         /*public static Metadata get(Metadata metadata, QueryPath path) {
227
228         }*/
229         public static Metadata get(Metadata metadata, QueryPath frame) {
230             if(frame.size() == 1) {
231                 return metadata.getProperties().get(frame.get(0).get());
232             } else {
233                 if (metadata.getDataType() == DataType.LIST){
234                         return get(metadata, frame, DataType.LIST);
235                 }
236                 else{
237                         return get(metadata.getProperties().get(frame.get(0).get()), frame.subPath(1, frame.size()));
238                 }
239             }
240         }
241
242         private static Metadata get(Metadata metadata, QueryPath frame, DataType type){
243                 if(type == DataType.LIST){
244                         return get(metadata.getProperties().get(QueryPath.getWildCard()), frame.subPath(1, frame.size()));
245                 }
246                 else{
247                        return get(metadata.getProperties().get(frame.get(0).get()), frame.subPath(1, frame.size()));
248                 }
249         }
250}