Skip to content

Commit

Permalink
Merge pull request #14 from Gruncan/v1.2a
Browse files Browse the repository at this point in the history
V1.2.0
  • Loading branch information
Gruncan authored Apr 15, 2023
2 parents dfa2fdf + c1145da commit 1546d17
Show file tree
Hide file tree
Showing 49 changed files with 1,245 additions and 77 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>

</dependencies>

<build>
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/com/http/SpotifyHttpServerProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@ public void runServer() {
if (!url.getHost().equals("127.0.0.1"))
url = new URL("https://127.0.0.1:8888/redirect/");


Desktop desktop = Desktop.getDesktop();
server = HttpServer.create(new InetSocketAddress(url.getPort()), 0);
this.server = HttpServer.create(new InetSocketAddress(url.getPort()), 0);
this.countDownLatch = new CountDownLatch(1);
server.createContext(url.getPath(), new RedirectHandler());
this.server.createContext(url.getPath(), new RedirectHandler());

desktop.browse(new URI(spotifyClientBuilder.buildAuthUrl()));
server.start();
desktop.browse(new URI(this.spotifyClientBuilder.buildAuthUrl()));
this.server.start();
} catch (IOException | URISyntaxException e) {
System.out.println("Unable to start server.");
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;


class JSON {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;


import java.lang.reflect.Array;
Expand Down Expand Up @@ -633,6 +633,7 @@ public JSONObject getJSONObject(int index) throws JSONException {
if (object instanceof JSONObject) {
return (JSONObject) object;
} else {
if (object == null || object.toString().equals("null")) return null;
throw JSON.typeMismatch(index, object, "JSONObject");
}
}
Expand All @@ -647,7 +648,7 @@ public JSONObject getModifiedJSONObject(int index) throws JSONException {
} else if (object instanceof Boolean) {
return new JSONObject(String.format("{\"value\": %b}", object));
} else if (object instanceof Double) {
return new JSONObject(String.format("{\"value\": %d}", object));
return new JSONObject(String.format("{\"value\": %f}", object));
} else if (object instanceof Integer) {
return new JSONObject(String.format("{\"value\": %d}", object));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;

// Note: this class was written without inspecting the non-free org.json sourcecode.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;


import java.beans.IntrospectionException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.spotify.json;
package com.json;

/**
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;


import java.util.ArrayList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.spotify.json;
package com.json;

// Note: this class was written without inspecting the non-free org.json sourcecode.

Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/spotify/SpotifyClient.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.spotify;

import com.spotify.requests.IRequest;
import com.spotify.requests.RequestResponse;
import com.spotify.requests.AbstractRequest;

public interface SpotifyClient {


// to be changed
RequestResponse executeRequest(IRequest request);
SpotifyResponse executeRequest(AbstractRequest request);


}
7 changes: 3 additions & 4 deletions src/main/java/com/spotify/SpotifyClientBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
import com.http.HttpRequest;
import com.http.HttpResponse;
import com.http.SpotifyHttpServerProvider;
import com.spotify.json.JSONObject;
import com.spotify.requests.IRequest;
import com.spotify.requests.RequestResponse;
import com.json.JSONObject;
import com.spotify.requests.AbstractRequest;
import com.spotify.requests.util.Scope;
import com.spotify.util.Util;

Expand Down Expand Up @@ -198,7 +197,7 @@ public SpotifyClientImp(String accessToken) {


@Override
public RequestResponse executeRequest(IRequest request) {
public SpotifyResponse executeRequest(AbstractRequest request) {
return request.execute(this.accessToken);
}
}
Expand Down
53 changes: 53 additions & 0 deletions src/main/java/com/spotify/SpotifyResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.spotify;

import com.json.JSONArray;
import com.json.JSONObject;
import com.spotify.objects.SpotifyObject;
import com.spotify.objects.SpotifySerializer;
import com.spotify.requests.RequestResponse;

import java.lang.reflect.Array;

public class SpotifyResponse extends SpotifySerializer {


private final RequestResponse requestResponse;
private final Class<? extends SpotifyObject> cls;
private String index = null;


public SpotifyResponse(RequestResponse response, Class<? extends SpotifyObject> cls) {
this.requestResponse = response;
this.cls = cls;
}

public SpotifyResponse(RequestResponse response, Class<? extends SpotifyObject> cls, String index) {
this(response, cls);
this.index = index;

}

public RequestResponse getRequestResponse() {
return this.requestResponse;
}

@SuppressWarnings("unchecked")
public <E extends SpotifyObject> E[] getSerialisedObjects() {
if (this.index == null) return null;
JSONArray jsonArray = this.requestResponse.ok().getJSONArray(this.index);
int length = jsonArray.length();
E[] array = (E[]) Array.newInstance(this.cls, length);
for (int i = 0; i < length; i++) {
JSONObject json = jsonArray.getJSONObject(i);
array[i] = (E) super.serializeObject(json, this.cls);
}
return array;
}


@SuppressWarnings("unchecked")
public <E extends SpotifyObject> E getSerialisedObject() {
return (E) super.serializeObject(this.requestResponse.ok(), cls);
}

}
18 changes: 18 additions & 0 deletions src/main/java/com/spotify/objects/SpotifyField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.spotify.objects;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SpotifyField {

// Since default can't be null, setting it to " is illegal json, therefore won't ever occur
String value() default "\"";

String[] path() default {};

}
9 changes: 9 additions & 0 deletions src/main/java/com/spotify/objects/SpotifyObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.spotify.objects;


import java.io.Serializable;

public interface SpotifyObject extends Serializable {


}
13 changes: 13 additions & 0 deletions src/main/java/com/spotify/objects/SpotifyOptional.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.spotify.objects;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SpotifyOptional {


}
13 changes: 13 additions & 0 deletions src/main/java/com/spotify/objects/SpotifySerialize.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.spotify.objects;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface SpotifySerialize {

Class<? extends SpotifyObject> value();

boolean isArray() default false;

}
134 changes: 134 additions & 0 deletions src/main/java/com/spotify/objects/SpotifySerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.spotify.objects;

import com.json.JSONArray;
import com.json.JSONObject;
import com.spotify.exceptions.SpotifySerializationException;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public abstract class SpotifySerializer {

@SuppressWarnings({"unchecked", "rawtypes"})
private <E extends Serializable> E serializer(Class<E> cls, JSONObject json) {
try {
if (cls.isEnum()) {
return (E) this.handleEnum((Class<? extends Enum>) cls, json.getString("value"));
}
Constructor<E> constructor = cls.getConstructor();
E e = constructor.newInstance();
SpotifyOptional notRequiredCls = cls.getAnnotation(SpotifyOptional.class);

boolean clsRequired = notRequiredCls != null;


for (Field field : cls.getDeclaredFields()) {
SpotifyField spotifyField = field.getAnnotation(SpotifyField.class);
// if not field not annotated ignore
if (spotifyField == null) continue;

SpotifyOptional spotifyNotRequired = field.getAnnotation(SpotifyOptional.class);

boolean fieldRequired = spotifyNotRequired != null;


boolean required = !(fieldRequired || clsRequired);

Class<?> fieldRawType = field.getType();
Class<? extends Serializable> fieldType;


if (fieldRawType.isPrimitive()) {
if (fieldRawType.equals(int.class))
fieldRawType = Integer.class;
else if (fieldRawType.equals(boolean.class))
fieldRawType = Boolean.class;
else if (fieldRawType.equals(double.class))
fieldRawType = Double.class;
else
continue;
}


if (Serializable.class.isAssignableFrom(fieldRawType))
fieldType = (Class<? extends Serializable>) fieldRawType;
else
continue;

String name = spotifyField.value();
if (name.equals("\""))
name = field.getName();


// Get jsonobject if deeper in hierarchy
JSONObject jsonPath = json;
for (String p : spotifyField.path())
jsonPath = jsonPath.getJSONObject(p);


//if field is not present and is required throw error can't serialize
if (!required && (jsonPath == null || jsonPath.isNull(name)))
continue;
else if (jsonPath == null || jsonPath.isNull(name))
throw new SpotifySerializationException(String.format("No mapping found for spotify required field: \"%s/%s\". " +
"Java class %s field: %s", String.join("/", spotifyField.path()), spotifyField.value(), cls, field.getName()));


field.setAccessible(true);

if (fieldType.isArray()) {
Class<?> componentRawType = fieldType.getComponentType();
Class<? extends Serializable> componentType = (Class<? extends Serializable>) componentRawType;


JSONArray jsonArray = jsonPath.getJSONArray(name);
field.set(e, this.createArray(componentType, jsonArray));
} else {
field.set(e, this.serializeField(fieldType, jsonPath, name));
}
field.setAccessible(false);
}
return e;

} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException | SpotifySerializationException a) {
a.printStackTrace();
return null;
}
}

private <E extends Serializable> E serializeField(Class<E> componentType, JSONObject jsonPath, String name) {
if (!SpotifyObject.class.isAssignableFrom(componentType))
return jsonPath.get(componentType, name);
else {
JSONObject jsonv = jsonPath.get(JSONObject.class, name);
if (jsonv == null) {
return this.serializer(componentType, jsonPath);
} else {
return this.serializer(componentType, jsonPath.get(JSONObject.class, name));
}
}
}

@SuppressWarnings("unchecked")
private <E extends Serializable> E[] createArray(Class<E> cls, JSONArray jsonArray) {
E[] array = (E[]) Array.newInstance(cls, jsonArray.length());
for (int i = 0; i < array.length; i++)
array[i] = this.serializeField(cls, jsonArray.getModifiedJSONObject(i), "value");
return array;
}

private <E extends Enum<E>> E handleEnum(Class<E> cls, String value) {
return Enum.valueOf(cls, value);
}

protected <S extends SpotifyObject> S serializeObject(JSONObject json, Class<S> cls) {
if (json == null) return null;
return this.serializer(cls, json);
}


}
Loading

0 comments on commit 1546d17

Please sign in to comment.