Skip to content

Commit 3a1d678

Browse files
refactor ObjectConverter, creating Utils, bitwise optimizations, preparation for variable deserialization and abolishment of scope runtime temporary inharitance, other refactorings,
1 parent ced0131 commit 3a1d678

26 files changed

+1316
-533
lines changed

SerialX-core/src/main/java/org/ugp/serialx/GenericScope.java

Lines changed: 120 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import java.util.function.Predicate;
1818

1919
import org.ugp.serialx.Utils.NULL;
20-
import org.ugp.serialx.converters.ArrayConverter;
2120
import org.ugp.serialx.converters.DataParser;
2221
import org.ugp.serialx.protocols.SerializationProtocol;
2322
import org.ugp.serialx.protocols.SerializationProtocol.ProtocolRegistry;
@@ -110,7 +109,7 @@ else if (obj instanceof Collection)
110109
else if (obj instanceof Map)
111110
return valuesCount() <= 0 && variables().equals(obj);
112111
else if (obj != null && obj.getClass().isArray())
113-
return variablesCount() <= 0 && Objects.deepEquals(toValArray(), ArrayConverter.fromAmbiguous(obj));
112+
return variablesCount() <= 0 && Objects.deepEquals(toValArray(), Utils.fromAmbiguousArray(obj));
114113
return super.equals(obj);
115114
}
116115

@@ -277,10 +276,82 @@ public <V extends ValT> V get(KeyT variableKey, V defaultValue)
277276
{
278277
V obj = (V) variables().get(variableKey);
279278
if (obj == null)
280-
return (V) defaultValue;
279+
return defaultValue;
281280
return obj instanceof NULL ? null : obj;
282281
}
283282

283+
/**
284+
* @param pathToValue | Array with variables creating path to required value, nested in multiple sub-scopes.
285+
*
286+
* @return Value of variable at given path. If no path is given (length is 0) then this {@link GenericScope} will be returned.<br>
287+
* If 1 path argument is given then this behaves similarly to {@link GenericScope#get(Object)}.<br>
288+
* if 2+ path arguments are given then it will search the sub-scopes and return first match value. For example:<br>
289+
* Consider this scope tree:<br>
290+
* <pre>
291+
* <code>
292+
* {
293+
* 125: {
294+
* "hello": {
295+
* "value" true
296+
* }
297+
* }
298+
* }
299+
* </code>
300+
* </pre>
301+
* Then to get value of "value" you can do <code>scope.get(125, "hello", "value")</code>!<br>
302+
* If there is no other variable called "value" in the scope tree then you can also simplify it to <code>scope.get("value")</code>, but make sure that there is no equally-named variable!<br>
303+
* Note: Make sure that you are not calling {@link GenericScope#get(Object, Object)} by accident when you are using inline vargas array (unspecified count of arguments)!
304+
*
305+
* @since 1.3.7
306+
*/
307+
@SuppressWarnings("unchecked")
308+
public <V extends ValT> V get(KeyT... pathToValue)
309+
{
310+
try
311+
{
312+
if (pathToValue.length <= 0)
313+
return (V) this;
314+
Object obj = get((KeyT) pathToValue[0]);
315+
if (obj instanceof GenericScope)
316+
return ((GenericScope<KeyT, V>) obj).get(pathToValue = Arrays.copyOfRange(pathToValue, 1, pathToValue.length));
317+
for (Map.Entry<KeyT, ValT> var : varEntrySet())
318+
if (var.getValue() instanceof GenericScope)
319+
try
320+
{
321+
GenericScope<KeyT, V> sc = (GenericScope<KeyT, V>) var.getValue();
322+
if ((sc = sc.getGenericScope(pathToValue[0])) != null)
323+
return sc.get(pathToValue = Arrays.copyOfRange(pathToValue, 1, pathToValue.length));
324+
}
325+
catch (Exception e) {}
326+
327+
return (V) obj;
328+
}
329+
catch (ClassCastException e)
330+
{}
331+
return null;
332+
}
333+
334+
/**
335+
* @param variableKey | Variables name.
336+
* @param cls | Default value to return.
337+
* @param defaultValue | Class that you want the obtained object to be converted into! Exact conversion algorithm can differ based on its implementations.
338+
*
339+
* @return Value of variable with name given converted to object of cls or defaultValue if there is no such a one!
340+
*
341+
* @throws Exception | If converting to object of cls failed from some reason! This can differ from implementation to implementation! By default it uses {@link GenericScope#toObject(cls)}
342+
*
343+
* @since 1.3.7
344+
*/
345+
public <V extends ValT> V get(KeyT variableKey, Class<V> cls, V defaultValue) throws Exception
346+
{
347+
V obj = get(variableKey, defaultValue);
348+
if (obj != null && obj.getClass() == cls)
349+
return obj;
350+
if (obj instanceof GenericScope)
351+
return ((GenericScope<?, ?>) obj).toObject(cls);
352+
return obj;
353+
}
354+
284355
/**
285356
* @param variableKey | Variables name to search for.
286357
*
@@ -312,7 +383,7 @@ public boolean containsIndependentValue(ValT value)
312383
* @param valueIndex | Index of independent value. Also can be negative, in this case u will get elements from back!
313384
* {@link IndexOutOfBoundsException} will be thrown if index is too big!
314385
*
315-
* @return Independent value with valueIndex.
386+
* @return Independent value with valueIndex of this {@link GenericScope}!
316387
*
317388
* @since 1.2.0
318389
*/
@@ -323,6 +394,26 @@ public <V extends ValT> V get(int valueIndex)
323394
return obj instanceof NULL ? null : obj;
324395
}
325396

397+
/**
398+
* @param valueIndex | Index of independent value. Also can be negative, in this case u will get elements from back!
399+
* @param cls | Class that you want the obtained object to be converted into! Exact conversion algorithm can differ based on its implementations.
400+
*
401+
* @return Independent value with valueIndex of this converted to object of cls!
402+
*
403+
* @throws Exception | If converting to object of cls failed from some reason! This can differ from implementation to implementation!
404+
*
405+
* @since 1.3.7
406+
*/
407+
public <V extends ValT> V get(int valueIndex, Class<V> cls) throws Exception
408+
{
409+
V obj = get(valueIndex);
410+
if (obj != null && obj.getClass() == cls)
411+
return obj;
412+
if (obj instanceof GenericScope)
413+
return ((GenericScope<?, ?>) obj).toObject(cls);
414+
return obj;
415+
}
416+
326417
/**
327418
* @param value | Independent value to add into array of values.
328419
*
@@ -383,41 +474,25 @@ public <K, V> GenericScope<K, V> getGenericScope(int scopeValueIndex)
383474
}
384475

385476
/**
386-
* @param scopesPath | Array with variables creating path to required scope.
477+
* @param pathToScope | Array with variables creating path to required scope.
387478
*
388-
* @return Sub-scope stored by variable with required name (last element) in inserted path or null if there is no such a one in inserted path. If there is more than one result, the first one found will be returned!
389-
* This search will also includes sub-scopes of scope but variables from lower ones are prioritize! <br>
479+
* @return Sub-scope stored by variable with required name (last element of pathToScope) or null if there is no such a one in inserted path. If there is more than one result, the first one found will be returned!
480+
* This search will also includes sub-scopes stored by variables of this scope while variables from lower ones are prioritize!<br>
390481
* If this function is called with no arguments then self will be returned!
391482
* Note: Remember that this search includes variables only, no values! <br>
392483
* Note: Also remember that this function will work only when this scope generically allows to store other scopes inside (when ValT is base class of {@link GenericScope})
393484
*
394485
* @since 1.2.0
395486
*/
396487
@SuppressWarnings("unchecked")
397-
public <K, V> GenericScope<K, V> getGenericScope(K... scopesPath)
488+
public <K, V> GenericScope<K, V> getGenericScope(K... pathToScope)
398489
{
399-
try
400-
{
401-
if (scopesPath.length <= 0)
402-
return (GenericScope<K, V>) this;
403-
Object obj = get((KeyT) scopesPath[0]);
404-
if (obj instanceof GenericScope)
405-
return ((GenericScope<K, V>) obj).getGenericScope(scopesPath = Arrays.copyOfRange(scopesPath, 1, scopesPath.length));
406-
for (Map.Entry<KeyT, ValT> var : varEntrySet())
407-
if (var.getValue() instanceof GenericScope)
408-
try
409-
{
410-
GenericScope<K, V> sc = (GenericScope<K, V>) var.getValue();
411-
if ((sc = sc.getGenericScope(scopesPath[0])) != null)
412-
return sc.getGenericScope(scopesPath = Arrays.copyOfRange(scopesPath, 1, scopesPath.length));
413-
}
414-
catch (Exception e) {}
415-
416-
if (containsVariable((KeyT) scopesPath[0]))
417-
LogProvider.instance.logErr("Variable with name \"" + scopesPath[0] + "\" does exists! However its value is not instance of scope, use \"get\" function instead if possible!", null);
418-
}
419-
catch (ClassCastException e)
420-
{}
490+
Object obj = get((KeyT[]) pathToScope);
491+
if (obj instanceof GenericScope)
492+
return (GenericScope<K, V>) obj;
493+
494+
if (containsVariable((KeyT) pathToScope[0]))
495+
LogProvider.instance.logErr("Variable with name \"" + pathToScope[0] + "\" does exists! However its value is not instance of scope, use \"get\" function instead if possible!", null);
421496
return null;
422497
}
423498

@@ -657,7 +732,7 @@ public GenericScope<KeyT, ValT> inheritParent()
657732
*
658733
* @since 1.3.0
659734
*/
660-
public GenericScope<KeyT, ValT> addAll(GenericScope<KeyT, ? extends ValT> scope)
735+
public GenericScope<KeyT, ValT> addAll(GenericScope<? extends KeyT, ? extends ValT> scope)
661736
{
662737
values().addAll(scope.values());
663738
variables().putAll(scope.variables());
@@ -719,23 +794,27 @@ public boolean isEmpty()
719794
*/
720795
public GenericScope<?, ?> getParent()
721796
{
722-
return getParent(false);
797+
return getParent(1);
723798
}
724799

725800
/**
726-
* @param absoluteParent | If true, absolute parent of this scope will be returned (parent of parent of parent...)!
727-
*
728-
* @return The parent scope of this scope or null if this scope has no parent such as default one in file.
801+
* @param depth | Positive number representing how many times will this method call itself... <br> For example 0 or less = this, 1 = parent, 2 = parentOfParent (parent.getParent()) and so on...
802+
* If you want to get the root parent (the one that has no parent), simply put a big number as depth. 99 should be enough!
803+
*
804+
* @return The parent scope based on depth or null if this scope has no parent which means its already root (default one in file).
805+
* If depth was bigger than 1, null will be never returned, last not null parent will be returned instead!<br>
729806
*
730807
* @since 1.3.2
731808
*/
732-
public GenericScope<?, ?> getParent(boolean absoluteParent)
809+
public GenericScope<?, ?> getParent(int depth)
733810
{
734-
if (!absoluteParent)
735-
return parent;
736-
GenericScope<?, ?> parent = this.parent;
737-
for (GenericScope<?, ?> tmpPar; parent != null && (tmpPar = parent.getParent()) != null; parent = tmpPar);
738-
return parent;
811+
if (depth < 1)
812+
return this;
813+
814+
GenericScope<?, ?> parentsParent;
815+
if (depth == 1 || parent == null || (parentsParent = parent.getParent(--depth)) == null)
816+
return parent;
817+
return parentsParent;
739818
}
740819

741820
/**

SerialX-core/src/main/java/org/ugp/serialx/LogProvider.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ public class LogProvider
1515
public static LogProvider instance = new LogProvider();
1616

1717
/**
18-
* @param object | Object to log in normal mode!
18+
* @param obj | Object to log in normal mode!
1919
*
2020
* @since 1.3.5
2121
*/
22-
public void logOut(Object object)
22+
public void logOut(Object obj)
2323
{
24-
System.out.println(object);
24+
System.out.println(obj);
2525
}
2626

2727
/**
28-
* @param object | Object to log in error mode!
28+
* @param obj | Object to log in error mode!
2929
* @param ex | Exception that cause the error!
3030
*
31+
* @throws RuntimeException | Of "ex" if exception re-throwing is enabled!
32+
*
3133
* @since 1.3.5
3234
*/
3335
public void logErr(Object obj, Throwable ex)

0 commit comments

Comments
 (0)