@@ -85,9 +85,10 @@ public class ApiClientBase implements Cloneable, Closeable { | |||
} | |||
public void removeHeaders () { headers = null; } | |||
public void setToken(String token) { | |||
public ApiClientBase setToken(String token) { | |||
this.token = token; | |||
this.tokenCtime = empty(token) ? 0 : now(); | |||
return this; | |||
} | |||
private long tokenCtime = 0; | |||
@@ -203,9 +203,9 @@ public class EntityConfig { | |||
updateWithAnnotation(clazz, clazz.getAnnotation(ECType.class)); | |||
updateWithAnnotation(clazz.getAnnotation(ECTypeList.class)); | |||
updateWithAnnotation(clazz.getAnnotation(ECTypeCreate.class)); | |||
updateWithAnnotation(clazz.getAnnotation(ECTypeUpdate.class)); | |||
updateWithAnnotation(clazz.getAnnotation(ECTypeDelete.class)); | |||
updateWithAnnotation(mainECAnnotation, clazz.getAnnotation(ECTypeCreate.class)); | |||
updateWithAnnotation(mainECAnnotation, clazz.getAnnotation(ECTypeUpdate.class)); | |||
updateWithAnnotation(mainECAnnotation, clazz.getAnnotation(ECTypeDelete.class)); | |||
updateWithAnnotation(clazz, clazz.getAnnotation(ECTypeURIs.class)); | |||
final Set<String> entityFields = new HashSet<>(fieldNamesWithAnnotations(clazz, ECField.class, ECSearchable.class, ECForeignKey.class)); | |||
@@ -260,8 +260,11 @@ public class EntityConfig { | |||
} | |||
/** Update properties with values from the given annotation. Doesn't override existing non-empty values! */ | |||
private EntityConfig updateWithAnnotation(ECTypeCreate annotation) { | |||
if (annotation == null) return this; | |||
private EntityConfig updateWithAnnotation(ECType type, ECTypeCreate annotation) { | |||
if (annotation == null) { | |||
if (type != null && empty(createMethod)) setCreateMethod(ECTypeCreate.DEFAULT_METHOD); | |||
return this; | |||
} | |||
if (empty(createMethod)) setCreateMethod(annotation.method()); | |||
if (empty(createUri)) setCreateUri((annotation.uri().startsWith(":") ? "" : uriPrefix) + annotation.uri()); | |||
@@ -270,8 +273,11 @@ public class EntityConfig { | |||
} | |||
/** Update properties with values from the given annotation. Doesn't override existing non-empty values! */ | |||
private EntityConfig updateWithAnnotation(ECTypeUpdate annotation) { | |||
if (annotation == null) return this; | |||
private EntityConfig updateWithAnnotation(ECType type, ECTypeUpdate annotation) { | |||
if (annotation == null) { | |||
if (type != null && empty(updateMethod)) setUpdateMethod(ECTypeUpdate.DEFAULT_METHOD); | |||
return this; | |||
} | |||
if (empty(updateMethod)) setUpdateMethod(annotation.method()); | |||
if (empty(updateUri)) setUpdateUri((annotation.uri().startsWith(":") ? "" : uriPrefix) + annotation.uri()); | |||
@@ -280,8 +286,11 @@ public class EntityConfig { | |||
} | |||
/** Update properties with values from the given annotation. Doesn't override existing non-empty values! */ | |||
private EntityConfig updateWithAnnotation(ECTypeDelete annotation) { | |||
if (annotation == null) return this; | |||
private EntityConfig updateWithAnnotation(ECType type, ECTypeDelete annotation) { | |||
if (annotation == null) { | |||
if (type != null && empty(deleteMethod)) setDeleteMethod(ECTypeDelete.DEFAULT_METHOD); | |||
return this; | |||
} | |||
if (empty(deleteMethod)) setDeleteMethod(annotation.method()); | |||
if (empty(deleteUri)) setDeleteUri((annotation.uri().startsWith(":") ? "" : uriPrefix) + annotation.uri()); | |||
@@ -276,7 +276,7 @@ public class ModelSetup { | |||
final ModelSetupListener listener, | |||
boolean update, | |||
final String runName) throws Exception { | |||
createEntity(api, entityConfig, request, context, listener, false, false, runName); | |||
createEntity(api, entityConfig, request, context, listener, update, false, runName); | |||
} | |||
protected static void createEntity(final ApiClientBase api, | |||
@@ -633,7 +633,7 @@ public class ModelSetup { | |||
} | |||
public boolean hasData(final boolean strict) { | |||
return IteratorUtils.toList(node.fieldNames()).stream().filter((n) -> !ArrayUtils.contains(entity.excludeUpdateFields(strict), n)).count() > 0; | |||
return IteratorUtils.toList(node.fieldNames()).stream().anyMatch((n) -> !ArrayUtils.contains(entity.excludeUpdateFields(strict), n)); | |||
} | |||
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||
@@ -7,6 +7,8 @@ import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) | |||
public @interface ECTypeCreate { | |||
String method() default "PUT"; | |||
String DEFAULT_METHOD = "PUT"; | |||
String method() default DEFAULT_METHOD; | |||
String uri() default ""; | |||
} |
@@ -7,6 +7,8 @@ import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) | |||
public @interface ECTypeDelete { | |||
String method() default "DELETE"; | |||
String DEFAULT_METHOD = "DELETE"; | |||
String method() default DEFAULT_METHOD; | |||
String uri() default ""; | |||
} |
@@ -7,6 +7,8 @@ import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) | |||
public @interface ECTypeUpdate { | |||
String method() default "POST"; | |||
String DEFAULT_METHOD = "POST"; | |||
String method() default DEFAULT_METHOD; | |||
String uri() default ""; | |||
} |
@@ -3,7 +3,7 @@ package org.cobbzilla.wizard; | |||
import com.fasterxml.jackson.databind.JsonNode; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import org.cobbzilla.util.io.FileUtil; | |||
import org.cobbzilla.util.collection.ExpirationMap; | |||
import org.cobbzilla.wizard.api.CrudOperation; | |||
import org.cobbzilla.wizard.client.ApiClientBase; | |||
import org.cobbzilla.wizard.model.Identifiable; | |||
@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.now; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.shortError; | |||
import static org.cobbzilla.util.io.FileUtil.extension; | |||
import static org.cobbzilla.util.io.FileUtil.toStringOrDie; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.util.json.JsonUtil.newArrayNode; | |||
import static org.cobbzilla.wizard.Unroll.unrollOrInvalid; | |||
@@ -34,7 +35,9 @@ public abstract class ModelSetupService { | |||
protected abstract String getEntityConfigsEndpoint(); | |||
protected abstract void setOwner(Identifiable owner, Identifiable entity); | |||
public Map<CrudOperation, Collection<Identifiable>> setupModel(Identifiable owner, File modelFile) { | |||
private Map<String, ModelSetupForOwner> setupCache = new ExpirationMap<>(); | |||
public Map<CrudOperation, Collection<Identifiable>> setupModel(ApiClientBase api, Identifiable owner, File modelFile) { | |||
File modelDir; | |||
final String ext = extension(modelFile); | |||
switch (ext.toLowerCase()) { | |||
@@ -64,12 +67,12 @@ public abstract class ModelSetupService { | |||
if (entityClass == null) throw invalidEx("err.entity.classInFilename.invalid"); | |||
// Does the file contain a single object? if so, wrap in array | |||
final JsonNode node = json(FileUtil.toStringOrDie(modelFile), JsonNode.class); | |||
final JsonNode node = json(toStringOrDie(modelFile), JsonNode.class); | |||
if (!node.isArray()) { | |||
final JsonNode arrayNode = newArrayNode().add(node); | |||
models.put(entityClass.getName(), json(arrayNode)); | |||
models.put(entityClass.getSimpleName(), json(arrayNode)); | |||
} else { | |||
models.put(entityClass.getName(), json(node)); | |||
models.put(entityClass.getSimpleName(), json(node)); | |||
} | |||
} else { | |||
resolver = new ManifestFileResolver(modelDir); | |||
@@ -77,13 +80,12 @@ public abstract class ModelSetupService { | |||
if (!manifest.exists()) { | |||
throw invalidEx("err.entity.manifest.required"); | |||
} | |||
models.put("manifest", manifest.getName()); | |||
models.put("manifest", toStringOrDie(manifest)); | |||
} | |||
try { | |||
final ApiClientBase api = getConfiguration().newApiClient(); | |||
final ModelSetupForOwner setup = new ModelSetupForOwner(owner); | |||
return setup.setup(api, models, resolver); | |||
return setupCache.computeIfAbsent(owner.getUuid(), k -> new ModelSetupForOwner(owner)) | |||
.setup(api, models, resolver); | |||
} catch (Exception e) { | |||
throw invalidEx("err.entity.setupError", shortError(e)); | |||
@@ -8,7 +8,6 @@ import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.exec.CommandLine; | |||
import org.cobbzilla.util.collection.ArrayUtil; | |||
import org.cobbzilla.util.collection.NameAndValue; | |||
import org.cobbzilla.util.http.ApiConnectionInfo; | |||
import org.cobbzilla.util.io.FileUtil; | |||
import org.cobbzilla.util.jdbc.DbDumpMode; | |||
import org.cobbzilla.util.jdbc.ResultSetBean; | |||
@@ -16,7 +15,6 @@ import org.cobbzilla.util.jdbc.UncheckedSqlException; | |||
import org.cobbzilla.util.string.StringUtil; | |||
import org.cobbzilla.util.system.Command; | |||
import org.cobbzilla.util.system.CommandResult; | |||
import org.cobbzilla.wizard.client.ApiClientBase; | |||
import org.cobbzilla.wizard.model.Identifiable; | |||
import org.cobbzilla.wizard.model.entityconfig.EntityReferences; | |||
import org.springframework.context.annotation.Bean; | |||
@@ -338,8 +336,4 @@ public class PgRestServerConfiguration extends RestServerConfiguration implement | |||
.generateConstraintSql(includeIndexes).toArray(new String[0]); | |||
} | |||
// warning: default ApiClientBase does not have an auth header set, will not work. | |||
// override in subclass | |||
public ApiClientBase newApiClient() { return new ApiClientBase(new ApiConnectionInfo(getLoopbackApiBase())); } | |||
} |