lombok delegation pattern not returning all methods in model.json(Json Exporter) for Tabs component - aem

I am using delegation pattern using lombok - hoping all getter method of parent super type will be exported in model.json
This is the sling model I wrote for Tabs component
package com.test.internal.models;
import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.export.json.ContainerExporter;
import com.adobe.cq.export.json.ExporterConstants;
import com.adobe.cq.wcm.core.components.internal.models.v1.TabsImpl;
import com.adobe.cq.wcm.core.components.models.Component;
import com.adobe.cq.wcm.core.components.models.Container;
import com.adobe.cq.wcm.core.components.models.ListItem;
import com.adobe.cq.wcm.core.components.models.Tabs;
import com.adobe.cq.wcm.core.components.models.datalayer.ComponentData;
import lombok.experimental.Delegate;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.*;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.annotations.via.ResourceSuperType;
import javax.inject.Inject;
import java.util.List;
#Model(
adaptables = {Resource.class, SlingHttpServletRequest.class},
adapters = {Tabs.class,ComponentExporter.class, ContainerExporter.class, Container.class},
resourceType = Accordion.RESOURCE_TYPE
)
#Exporter(
name = ExporterConstants.SLING_MODEL_EXPORTER_NAME,
extensions = ExporterConstants.SLING_MODEL_EXTENSION
)
public class Accordion implements Tabs {
static final String RESOURCE_TYPE = "test/components/accordion";
#Self #Via(type = ResourceSuperType.class)
#Delegate(types = Tabs.class,excludes = DelegationExclusion.class)
private com.adobe.cq.wcm.core.components.models.Tabs delegate;
#Override
public String getActiveItem() {
return "test";
}
private interface DelegationExclusion { // Here we define the methods we want to override
String getActiveItem();
}
}
I am trying to override the getActiveItem method for Tabs component. But it's not populating the items properly - they are empty in the json - just returning the overridden method in the json -
"accordion": {
"items": [],
"activeItem": "test",
":itemsOrder": [],
":items": {}
}
when I remove this Sling model from the bundle - the OOTB sling model comes into picture and returns everything -
"accordion": {
"id": "accordion-5248ba2449",
"activeItem": "item_1",
":itemsOrder": [
"item_1",
"item_2",
"ctabutton"
],
":items": {
"item_1": {
"gridClassNames": "aem-Grid aem-Grid--12 aem-Grid--default--12",
"columnClassNames": {
"backbutton": "aem-GridColumn aem-GridColumn--default--12"
},
"columnCount": 12,
"allowedComponents": {
"components": [],
"applicable": false
},
":itemsOrder": [
"backbutton"
],
":items": {
"backbutton": {
":type": "test/components/backbutton",
"btnLabel": "View More"
}
},
":type": "test/components/container",
"cq:panelTitle": "FAQ 1"
},
"item_2": {
"gridClassNames": "aem-Grid aem-Grid--12 aem-Grid--default--12",
"columnClassNames": {},
"columnCount": 12,
"allowedComponents": {
"components": [],
"applicable": false
},
":itemsOrder": [],
":items": {},
":type": "test/components/container",
"cq:panelTitle": "FAQ 2"
},
"ctabutton": {
":type": "test/components/ctabutton",
"btnAlignment": "left",
"lightboxId": "sadasdasdasdasdas",
"btnType": "cta-primary",
"btnLabel": "View More",
"openLightbox": "true",
"cq:panelTitle": null
}
},
":type": "test/components/accordion"
}
can someone please let me know what is missing in sling model that it's not returning the items properly

Here is working example from project, should help you.
#Model(
adaptables = SlingHttpServletRequest.class,
adapters = { Tabs.class, ComponentExporter.class, ContainerExporter.class },
resourceType = absModel.TABS_RESOURCE_TYPE,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
#Exporter(
name = ExporterConstants.SLING_MODEL_EXPORTER_NAME,
extensions = ExporterConstants.SLING_MODEL_EXTENSION
)
#JsonSerialize(as = TabsModel.class)
public class TabsModel implements Tabs {
protected static final String TABS_RESOURCE_TYPE = "myproject/components/tabs";
#Self
private SlingHttpServletRequest request;
#Self
#Via(type = ResourceSuperType.class)
#Delegate(excludes = Excludes.class)
private Tabs tabs;
#Override
public String getExportedType() {
return this.request.getResource().getResourceType();
}
private interface Excludes {
String getExportedType();
}
}

Related

White Screen for Launch External App in Ionic 4

I have a page that would like to launch external app when a button is clicked and the function goToApp() should run.
Following is my code for on the ts file but everything on the page could be loaded until the point I added
import { AppLauncher, AppLauncherOptions } from '#ionic-native/app-launcher/ngx';
Which right after it the page doesn't load anymore. There is no error code returned. Any idea? Thanks in advance.
import { Component,OnInit,Input } from '#angular/core';
import { AppLauncher, AppLauncherOptions } from '#ionic-native/app-launcher/ngx';
import { ModalController, Platform } from '#ionic/angular';
import { DomSanitizer,SafeResourceUrl } from '#angular/platform-browser';
/*
Generated class for the Posts page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-fsfastcheck',
templateUrl: 'fsfastcheck.html',
styleUrls: ['fsfastcheck.scss'],
})
export class FSFastCheckPage implements OnInit {
#Input()
url: string = "https://eastchenconsultancy.com/feng-shui-fast-check/";
url2: string = "https://eastchenconsultancy.com/appointment-list/";
urlSafe: SafeResourceUrl;
urlSafe2: SafeResourceUrl;
mySegment: string = 'travelrequest';
constructor(
public modalView: ModalController,
public sanitizer: DomSanitizer,
private appLauncher: AppLauncher, private platform: Platform) { }
ngOnInit() {
this.urlSafe= this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
this.urlSafe2= this.sanitizer.bypassSecurityTrustResourceUrl(this.url2);
}
close() {
this.modalView.dismiss();
}
goToApp() {
const options: AppLauncherOptions = { }
if(this.platform.is('ios')) {
options.packageName = 'com.apple.compass'
} else {
options.packageName = 'com.gn.android.compass'
}
this.appLauncher.canLaunch(options)
.then((canLaunch: boolean) => console.log('Compass is available'))
.catch((error: any) => console.error('Compass is not available'));
}
}
Have you followed the standard part which you need to do when adding new modules to your app:
https://ionicframework.com/docs/native/overview#angular
Basically, you need to inject the module into the app:
// app.module.ts
import { AppLauncher } from '#ionic-native/app-launcher/ngx';
...
#NgModule({
...
providers: [
...
AppLauncher
...
]
...
})
export class AppModule { }

Dynamically change material-dropdown-selection options using searchbox with keyup event in AngularDart

I have a dropdown menu with a search box to select out of about 1000 Options which are hierarchical. I begin to show top categories 1, 2, 3 in the dropdown. If you enter, say '1' a filter I implemented will now show subcategories 11, 12, .. of 1 only. This filter is called using keyup event on material-select-searchbox. I get a 'Expression has changed after it was checked'.
I suspect I get this error because I cannot modify parent input params just like that. I tried to solve the problem implementing the event handler in the parent component, modifying a parent variable (StringSelectionOptions categories in categories-selector.dart) that is an input to the material-select-searchbox (in categories-selector.html) - but this does not work.
I also tried fiddling around with #ViewChild but - without proper results.
I heard about StreamController and EventBusses, but I am not sure how to use these to solve my problem using library components (i.e. MaterialDropdownSelectComponent and MaterialSelectSearchboxComponent).
categories.dart
class Categories {
static final List<Category> categories = [
["1", "", "Category 1"]
["2", "", "Category 2"]
["11", "1", "Category 11 - Subcategory of 1"]
["12", "1", "Category 12 - Subcategory of 1"]
["21", "2", "Category 21 - Subcategory of 2"]
["22", "2", "Category 22 - Subcategory of 2"]
//... a thousand more ...
].map(
(c) => Category(c.first, els[1], els.first + " " + els.last)
).toList();
List<Category> filter(String searchterm){
return categories.where( (nc) =>
nc.parent == parent ).map((nc) => nc).toList();
}
}
class Category implements HasUIDisplayName {
String code;
String parent;
String label;
Category(this.code, this.parent, this.label);
#override
String toString() => label;
}
categories-selector.dart: imports
import 'dart:async';
import 'package:angular/angular.dart';
import 'package:angular_components/material_button/material_button.dart';
import 'package:angular_components/material_icon/material_icon.dart';
import 'package:angular_components/material_select/material_dropdown_select.dart';
import 'package:angular_components/material_select/material_select_searchbox.dart';
import 'package:angular_components/model/selection/string_selection_options.dart';
import 'package:right_scenario_explorer/src/activity_editor/scope_collapse_mixin.dart';
import 'package:right_scenario_explorer/src/company/activity.dart';
import 'package:right_scenario_explorer/src/company/emission.dart';
import 'package:right_scenario_explorer/src/utils/formatter.dart';
import 'package:right_scenario_explorer/src/utils/nace_codes.dart';
categories-selector.dart: code
#Component(
exports: [Formatter, Categories],
selector: "categories-selector",
templateUrl: "categories-selector.html",
directives: [
coreDirectives,
MaterialDropdownSelectComponent,
MaterialSelectSearchboxComponent,
MaterialButtonComponent,
MaterialIconComponent,
]
)
class CategoriesSelector extends OnInit with {
#Output()
Category selectedCategory;
StringSelectionOptions<Category> categories;
#override
void ngOnInit() {
getCategoryOptions("");
}
void getCategoryOptions(String searchterm) {
Categories categories = new Categories();
var selectedOptions = categories.filter(searchterm);
categoryOptions = StringSelectionOptions(selectedOptions);
}
void categorySearchBoxEventHandler(dynamic event){
getCategoryOptions(event.target.value);
}
void updateSelectedCategory(Category category) {
selectedCategory = category;
}
}
categories-selector.html
<div>
<material-dropdown-select
buttonAriaRole="combobox"
[buttonText]="selectedCategory == null ? 'None' : selectedCategory.toString()"
[options]="categories"
(selection)="updateSelectedCategory($event)"
[listAutoFocus]="false"
[activateFirstOption]="false"
<div header>
<material-select-searchbox
(keyup)="categorySearchBoxEventHandler"
label="Search..."
[filterable]="categories">
</material-select-searchbox>
</div>
</material-dropdown-select>
</div>
I would like to know how I can modify the options of material-dropdown-select from the keyup event of the material-select-searchbox. Any suggestions are much appreciated! Thank you!
You could try material-auto-suggest-input
that has been made to dynamically update options when you enter a value.

Showing contact from the contact loader Manager

I am showing the contact list from the contact table but not able to get the phone number using the same on RecyclerView.My code is -
package com.oodles.oodlesapprtc;
import android.annotation.SuppressLint;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.ArrayList;
/**
* Created by ankita on 13/4/17.
*/
public class LoginUserActivity extends AppCompatActivity {
public static final int CONTACT_LOADER_ID = 78;
RecyclerView loginUserRecycler;
ArrayList<ContactBeans> contactBeanses;
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
" COLLATE LOCALIZED ASC";
private static final String[] PROJECTION2 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI,ContactsContract.Contacts.HAS_PHONE_NUMBER
};
private static final String[] PROJECTION3 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI, ContactsContract.Contacts.LOOKUP_KEY
};
private static final String[] PROJECTION = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER
};
// private static final String[] PROJECTION1 = {
// ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
// ContactsContract.CommonDataKinds.Phone.NUMBER
// };
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_user_activity);
initViews();
}
private void initViews() {
getLoaderManager().initLoader(0, null, contactLoaderManager);
initRecycler();
}
private void initRecycler() {
loginUserRecycler = (RecyclerView) findViewById(R.id.loginUserRecycler);
loginUserRecycler.setLayoutManager(new LinearLayoutManager(this));
loginUserRecycler.setItemAnimator(new DefaultItemAnimator());
}
LoaderManager.LoaderCallbacks<Cursor> contactLoaderManager = new LoaderManager.LoaderCallbacks<Cursor>() {
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// String[] projectionFields = new String[]{ContactsContract.Contacts._ID,
// ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.PhoneLookup.NORMALIZED_NUMBER,
// ContactsContract.Contacts.PHOTO_URI};
// Construct the loader
// Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
// ContactsContract.Contacts.CONTENT_URI
// Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
// Uri.encode(phoneNumber));
CursorLoader cursorLoader = new CursorLoader(LoginUserActivity.this,
ContactsContract.Contacts.CONTENT_URI, // URI
PROJECTION2, // projection fields
null, // the selection criteria
null, // the selection args
sortOrder // the sort order
);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
loginUserRecycler.setAdapter(new CursorRecyclerAdapter(LoginUserActivity.this, data));
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
}
My Adapter is -
package com.oodles.oodlesapprtc;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by ankita on 13/4/17.
*/
public class CursorRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> {
private Cursor mCursor;
private final int mNameColIdx,
mIdColIdx;
int phoneNumber;
int hasPhoneNumber;
private Context mContext;
public CursorRecyclerAdapter(Context context, Cursor cursor) {
mCursor = cursor;
this.mContext = context;
mNameColIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
mIdColIdx = cursor.getColumnIndex(ContactsContract.Contacts._ID);
hasPhoneNumber = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
}
#Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View listItemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_row, parent, false);
return new ContactViewHolder(listItemView);
}
#Override
public void onBindViewHolder(ContactViewHolder contactViewHolder, int pos) {
mCursor.moveToPosition(pos);
String contactName = mCursor.getString(mNameColIdx);
long contactId = mCursor.getLong(mIdColIdx);
Contact c = new Contact();
Log.e("ddhdhdhhdhdhdhd",hasPhoneNumber+"");
c.name = contactName;
c.number = getPhoneNumberFromContactId(contactId);
c.profilePic = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
getPhoneNumberFromContactId(contactId);
contactViewHolder.bind(c);
}
private String getPhoneNumberFromContactId(long contactId) {
String contactNumber = "8874675724";
return contactNumber;
}
#Override
public int getItemCount() {
return mCursor.getCount();
}
}
How can I get the phone number for the same i am getting a cursorindexoutofbound exception and has phone number value as 3 but it can be only 0 or 1 why it is 3 i don't understand this.
Can Anyone please explain this to me also please explain how the contact fetch works
You have a few issues in the code:
You're querying on the Contacts table, but sorting using a CommonDataKinds.Phone table field, that's not good, you can sort using Contacts.DISPLAY_NAME_PRIMARY instead.
cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER) gives you a column index, not the value of the field, that's why you're getting 3 (it's the 4rd field defined in PROJECTION2), change hasPhoneNumber to mHasPhoneNumberIdx to avoid confusion.
add hasPhoneNumber = mCursor.getInt(mHasPhoneNumberIdx); to your onBindViewHolder method, to get the actual value.
Running a long command like a real implementation of getPhoneNumberFromContactId within onBindViewHolder is really bad... you should change your main query so you do two big queries, one for all contacts, one for all phones, and then use some HashMap to get a phone using a contact-id.

ReflectiveInjector throws InvalidProviderError

I am trying to inject 2 services into generic classes using ReflectiveInjector as seen in this SO
The first time I call ReflectiveInjector on DebugService it works completely fine, however if I then replace this with CourseService, I recieve the following InvalidProviderError:
Uncaught InvalidProviderError_nativeError: Error: Invalid provider - only instances of Provider and Type are allowed, got: undefined
This is the generic class where I am trying to inject the services.
Media.ts
////////////////////////////////////////////////////////////////////////////////////////
import { ReflectiveInjector } from '#angular/core';
// other imports
////////////////////////////////////////////////////////////////////////////////////////
import { CourseService , DebugService } from 'app/services';
//other imports
////////////////////////////////////////////////////////////////////////////////////////
export class Media {
private sanitizer: DomSanitizer;
private courseService: CourseService;
private debug: DebugService;
constructor(_audio: File[], _images: File[], _videos: File[] ) {
// works fine
var injector = ReflectiveInjector.resolveAndCreate([DebugService]);
this.debug = injector.get(DebugService);
// throws InvalidProviderError
var injector2 = ReflectiveInjector.resolveAndCreate([CourseService]);
this.courseService = injector2.get(CourseService);
}
The 2 services are as follows:
debug.service.ts
////////////////////////////////////////////////////////////////////////////////////////
import { Injectable } from '#angular/core';
////////////////////////////////////////////////////////////////////////////////////////
import { environment } from '../../environments/environment';
////////////////////////////////////////////////////////////////////////////////////////
#Injectable()
export class DebugService {
constructor() {
/*stuff*/
}
}
course-service.service.ts
////////////////////////////////////////////////////////////////////////////////////////
import { Injectable, EventEmitter, Output } from '#angular/core';
import { Router } from '#angular/router';
import { Title, DomSanitizer, SafeResourceUrl, SafeUrl} from '#angular/platform-browser';
////////////////////////////////////////////////////////////////////////////////////////
import { DebugService } from 'app/services';
////////////////////////////////////////////////////////////////////////////////////////
#Injectable()
export class CourseService {
#Output() preloadData = new EventEmitter<any>();
// Constructor 1 - called on instantiation of class
constructor(
private sanitizer: DomSanitizer,
private router: Router,
private titleService: Title,
private debug: DebugService
) { /*stuff*/ }
These services were successfully being used in the Media class prior, when I was manually passing CourseService and DebugService as params to the Media constructor, however wanted to get away from this as it seemed very 'clunky' compared to this more streamlined approach.
i.e.
export class Media {
/*stuff*/
constructor(_audio: File[], _images: File[], _videos: File[], _courseService: CourseService, _debugService: DebugService ) { /*stuff*/ }
}
Media is currently defined within another class's constructor:
var preloader = new Preloader(
new Media(
// Audio Files
[
new File(0, './app/assets/video/Example1.mp3')
],
// Image Files
[
],
// Video Files
[
new File(0, './app/assets/video/Example1.mp4')
]
)
//...

custom java annotations ind javadoc / doxygen

i have build a custom annotation like
package com.uc4.ucdf.control.xgui;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Documented
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface XGUIElement {
public String Name();
public String Description();
public XGUIAttribute[] Attributes();
public String CodeSnipet();
}
and
package com.uc4.ucdf.control.xgui;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Documented
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface XGUIAttribute {
public String Name();
public String ValueType();
public String Description();
}
in my class file i get this annotation
#XGUIElement( Name = "dialog",
Description = "this component provides a empty internal window with a title and some properties like if its minimizable, maximizable",
CodeSnipet = "<dialog id=\"myDialog\" text=\"Hello World\">",
Attributes = {
#XGUIAttribute(Description = "Set the width of the Dialog", Name = "width", ValueType = "Integer"),
#XGUIAttribute(Description = "Set the height of the Dialog", Name = "height", ValueType = "Integer"),
#XGUIAttribute(Description = "1 for true; 0 for false", Name = "top", ValueType = "Integer"),
#XGUIAttribute(Description = "Set the left position of this dialog", Name = "left", ValueType = "Integer"),
#XGUIAttribute(Description = "Allows you to set the dialog over all not ontop dialogs 1 for true; 0 for false ", Name = "ontop", ValueType = "Integer")
}
)
this works create and i can read the single values in my swingComponent
but i should bring this annoation into the javaDoc build with Doxygen.
so why i can't see the annotation in my javadoc und how i can fromated it into a tablelist of all attributes.